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

@ -133,8 +133,9 @@ session_alloc(SERVICE *service, DCB *client_dcb)
session->router_session =
service->router->newSession(service->router_instance,
session);
if (session->router_session == NULL) {
if (session->router_session == NULL)
{
/**
* Inform other threads that session is closing.
*/
@ -153,7 +154,6 @@ session_alloc(SERVICE *service, DCB *client_dcb)
goto return_session;
}
/*
* Pending filter chain being setup set the head of the chain to
* 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)
{
session_free(session);
spinlock_release(&session->ses_lock);
session_free(session);
client_dcb->session = NULL;
session = NULL;
LOGIF(LE, (skygw_log_write_flush(
@ -212,10 +213,13 @@ session_alloc(SERVICE *service, DCB *client_dcb)
else
{
session->state = SESSION_STATE_ROUTER_READY;
session->next = allSessions;
spinlock_release(&session->ses_lock);
spinlock_acquire(&session_spin);
session->next = allSessions;
allSessions = session;
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);
CHK_SESSION(session);
}

View File

@ -378,7 +378,6 @@ static int gw_read_backend_event(DCB *dcb) {
ERRACT_REPLY_CLIENT,
&succp);
gwbuf_free(errbuf);
ss_dassert(!succp);
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
"%lu [gw_read_backend_event] "
@ -854,8 +853,12 @@ static int gw_error_backend_event(DCB *dcb)
&succp);
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);
session->state = SESSION_STATE_STOPPING;
spinlock_release(&session->ses_lock);
@ -1082,8 +1085,8 @@ gw_backend_close(DCB *dcb)
mysql_protocol_done(dcb);
/**
* If session->state is set to STOPPING the client and the session must
* be closed too.
* If session->state is STOPPING, start closing client session.
* Otherwise only this backend connection is closed.
*/
if (session != NULL && session->state == SESSION_STATE_STOPPING)
{

View File

@ -830,7 +830,7 @@ int gw_read_client_event(
}
/** succeed */
if (rc)
if (rc)
{
rc = 0; /**< here '0' means success */
}
@ -850,7 +850,6 @@ int gw_read_client_event(
"Error : Routing the query failed. "
"Session will be closed.")));
dcb_close(dcb);
}
}
@ -1363,7 +1362,6 @@ gw_client_close(DCB *dcb)
SESSION* session;
ROUTER_OBJECT* router;
void* router_instance;
void* rsession;
#if defined(SS_DEBUG)
MySQLProtocol* protocol = (MySQLProtocol *)dcb->protocol;
if (dcb->state == DCB_STATE_POLLING ||
@ -1380,7 +1378,7 @@ gw_client_close(DCB *dcb)
* session may be NULL if session_alloc failed.
* In that case, router session wasn't created.
*/
if (session != NULL)
if (session != NULL)
{
CHK_SESSION(session);
spinlock_acquire(&session->ses_lock);
@ -1389,13 +1387,22 @@ gw_client_close(DCB *dcb)
{
session->state = SESSION_STATE_STOPPING;
}
spinlock_release(&session->ses_lock);
router = session->service->router;
router_instance = session->service->router_instance;
rsession = session->router_session;
/** Close router session and all its connections */
router->closeSession(router_instance, rsession);
router_instance = session->service->router_instance;
router = session->service->router;
/**
* 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;
}