Added protected state check to mysql_client.c, fixed locking in session.c
This commit is contained in:
VilhoRaatikka
2014-11-10 14:07:51 +02:00
parent d1772e300e
commit 3b07449daa
3 changed files with 38 additions and 24 deletions

View File

@ -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);
} }

View File

@ -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)
{ {

View File

@ -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;
} }