Fix to bug #614, http://bugs.skysql.com/show_bug.cgi?id=614
Added protected state check to mysql_client.c, fixed locking in session.c
This commit is contained in:
@ -134,7 +134,8 @@ session_alloc(SERVICE *service, DCB *client_dcb)
|
|||||||
service->router->newSession(service->router_instance,
|
service->router->newSession(service->router_instance,
|
||||||
session);
|
session);
|
||||||
|
|
||||||
if (session->router_session == NULL) {
|
if (session->router_session == NULL)
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* Inform other threads that session is closing.
|
* Inform other threads that session is closing.
|
||||||
*/
|
*/
|
||||||
@ -153,7 +154,6 @@ session_alloc(SERVICE *service, DCB *client_dcb)
|
|||||||
|
|
||||||
goto return_session;
|
goto return_session;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pending filter chain being setup set the head of the chain to
|
* Pending filter chain being setup set the head of the chain to
|
||||||
* be the router. As filters are inserted the current head will
|
* be the router. As filters are inserted the current head will
|
||||||
@ -196,11 +196,12 @@ session_alloc(SERVICE *service, DCB *client_dcb)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spinlock_acquire(&session_spin);
|
spinlock_acquire(&session->ses_lock);
|
||||||
|
|
||||||
if (session->state != SESSION_STATE_READY)
|
if (session->state != SESSION_STATE_READY)
|
||||||
{
|
{
|
||||||
session_free(session);
|
spinlock_release(&session->ses_lock);
|
||||||
|
session_free(session);
|
||||||
client_dcb->session = NULL;
|
client_dcb->session = NULL;
|
||||||
session = NULL;
|
session = NULL;
|
||||||
LOGIF(LE, (skygw_log_write_flush(
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
@ -212,10 +213,13 @@ session_alloc(SERVICE *service, DCB *client_dcb)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
session->state = SESSION_STATE_ROUTER_READY;
|
session->state = SESSION_STATE_ROUTER_READY;
|
||||||
session->next = allSessions;
|
spinlock_release(&session->ses_lock);
|
||||||
|
spinlock_acquire(&session_spin);
|
||||||
|
session->next = allSessions;
|
||||||
allSessions = session;
|
allSessions = session;
|
||||||
spinlock_release(&session_spin);
|
spinlock_release(&session_spin);
|
||||||
atomic_add(&service->stats.n_sessions, 1);
|
|
||||||
|
atomic_add(&service->stats.n_sessions, 1);
|
||||||
atomic_add(&service->stats.n_current, 1);
|
atomic_add(&service->stats.n_current, 1);
|
||||||
CHK_SESSION(session);
|
CHK_SESSION(session);
|
||||||
}
|
}
|
||||||
|
@ -378,7 +378,6 @@ static int gw_read_backend_event(DCB *dcb) {
|
|||||||
ERRACT_REPLY_CLIENT,
|
ERRACT_REPLY_CLIENT,
|
||||||
&succp);
|
&succp);
|
||||||
gwbuf_free(errbuf);
|
gwbuf_free(errbuf);
|
||||||
ss_dassert(!succp);
|
|
||||||
LOGIF(LD, (skygw_log_write(
|
LOGIF(LD, (skygw_log_write(
|
||||||
LOGFILE_DEBUG,
|
LOGFILE_DEBUG,
|
||||||
"%lu [gw_read_backend_event] "
|
"%lu [gw_read_backend_event] "
|
||||||
@ -854,8 +853,12 @@ static int gw_error_backend_event(DCB *dcb)
|
|||||||
&succp);
|
&succp);
|
||||||
gwbuf_free(errbuf);
|
gwbuf_free(errbuf);
|
||||||
|
|
||||||
/** There are not required backends available, close session. */
|
/**
|
||||||
if (!succp) {
|
* If error handler fails it means that routing session can't continue
|
||||||
|
* and it must be closed. In success, only this DCB is closed.
|
||||||
|
*/
|
||||||
|
if (!succp)
|
||||||
|
{
|
||||||
spinlock_acquire(&session->ses_lock);
|
spinlock_acquire(&session->ses_lock);
|
||||||
session->state = SESSION_STATE_STOPPING;
|
session->state = SESSION_STATE_STOPPING;
|
||||||
spinlock_release(&session->ses_lock);
|
spinlock_release(&session->ses_lock);
|
||||||
@ -1082,8 +1085,8 @@ gw_backend_close(DCB *dcb)
|
|||||||
mysql_protocol_done(dcb);
|
mysql_protocol_done(dcb);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If session->state is set to STOPPING the client and the session must
|
* If session->state is STOPPING, start closing client session.
|
||||||
* be closed too.
|
* Otherwise only this backend connection is closed.
|
||||||
*/
|
*/
|
||||||
if (session != NULL && session->state == SESSION_STATE_STOPPING)
|
if (session != NULL && session->state == SESSION_STATE_STOPPING)
|
||||||
{
|
{
|
||||||
|
@ -850,7 +850,6 @@ int gw_read_client_event(
|
|||||||
"Error : Routing the query failed. "
|
"Error : Routing the query failed. "
|
||||||
"Session will be closed.")));
|
"Session will be closed.")));
|
||||||
|
|
||||||
|
|
||||||
dcb_close(dcb);
|
dcb_close(dcb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1363,7 +1362,6 @@ gw_client_close(DCB *dcb)
|
|||||||
SESSION* session;
|
SESSION* session;
|
||||||
ROUTER_OBJECT* router;
|
ROUTER_OBJECT* router;
|
||||||
void* router_instance;
|
void* router_instance;
|
||||||
void* rsession;
|
|
||||||
#if defined(SS_DEBUG)
|
#if defined(SS_DEBUG)
|
||||||
MySQLProtocol* protocol = (MySQLProtocol *)dcb->protocol;
|
MySQLProtocol* protocol = (MySQLProtocol *)dcb->protocol;
|
||||||
if (dcb->state == DCB_STATE_POLLING ||
|
if (dcb->state == DCB_STATE_POLLING ||
|
||||||
@ -1389,13 +1387,22 @@ gw_client_close(DCB *dcb)
|
|||||||
{
|
{
|
||||||
session->state = SESSION_STATE_STOPPING;
|
session->state = SESSION_STATE_STOPPING;
|
||||||
}
|
}
|
||||||
spinlock_release(&session->ses_lock);
|
|
||||||
|
|
||||||
router = session->service->router;
|
|
||||||
router_instance = session->service->router_instance;
|
router_instance = session->service->router_instance;
|
||||||
rsession = session->router_session;
|
router = session->service->router;
|
||||||
/** Close router session and all its connections */
|
/**
|
||||||
router->closeSession(router_instance, rsession);
|
* If router session is being created concurrently router
|
||||||
|
* session might be NULL and it shouldn't be closed.
|
||||||
|
*/
|
||||||
|
if (session->router_session != NULL)
|
||||||
|
{
|
||||||
|
spinlock_release(&session->ses_lock);
|
||||||
|
/** Close router session and all its connections */
|
||||||
|
router->closeSession(router_instance, session->router_session);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
spinlock_release(&session->ses_lock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user