Fix bug in dcb; rearrange mysql_backend gw_backend_close to cope with receiving DCB that is no longer linked to a session.

This commit is contained in:
counterpoint
2015-06-09 12:03:58 +01:00
parent d0e92a15f8
commit 393e25e953
2 changed files with 23 additions and 19 deletions

View File

@ -1331,6 +1331,7 @@ dcb_close(DCB *dcb)
dcb->session = NULL; dcb->session = NULL;
spinlock_release(&dcb->server->persistlock); spinlock_release(&dcb->server->persistlock);
atomic_add(&dcb->server->stats.n_persistent, 1); atomic_add(&dcb->server->stats.n_persistent, 1);
atomic_add(&dcb->server->stats.n_current, -1);
} }
else else
{ {

View File

@ -1140,7 +1140,6 @@ gw_backend_close(DCB *dcb)
CHK_DCB(dcb); CHK_DCB(dcb);
session = dcb->session; session = dcb->session;
CHK_SESSION(session);
LOGIF(LD, (skygw_log_write(LOGFILE_DEBUG, LOGIF(LD, (skygw_log_write(LOGFILE_DEBUG,
"%lu [gw_backend_close]", "%lu [gw_backend_close]",
@ -1153,21 +1152,24 @@ gw_backend_close(DCB *dcb)
mysql_send_com_quit(dcb, 0, quitbuf); mysql_send_com_quit(dcb, 0, quitbuf);
mysql_protocol_done(dcb); mysql_protocol_done(dcb);
/**
* The lock is needed only to protect the read of session->state and if (session)
* session->client values. Client's state may change by other thread {
* but client's close and adding client's DCB to zombies list is executed CHK_SESSION(session);
* only if client's DCB's state does _not_ change in parallel. /**
*/ * The lock is needed only to protect the read of session->state and
spinlock_acquire(&session->ses_lock); * session->client values. Client's state may change by other thread
/** * but client's close and adding client's DCB to zombies list is executed
* If session->state is STOPPING, start closing client session. * only if client's DCB's state does _not_ change in parallel.
* Otherwise only this backend connection is closed. */
*/ spinlock_acquire(&session->ses_lock);
if (session != NULL && /**
session->state == SESSION_STATE_STOPPING && * If session->state is STOPPING, start closing client session.
* Otherwise only this backend connection is closed.
*/
if (session->state == SESSION_STATE_STOPPING &&
session->client != NULL) session->client != NULL)
{ {
if (session->client->state == DCB_STATE_POLLING) if (session->client->state == DCB_STATE_POLLING)
{ {
spinlock_release(&session->ses_lock); spinlock_release(&session->ses_lock);
@ -1179,11 +1181,12 @@ gw_backend_close(DCB *dcb)
{ {
spinlock_release(&session->ses_lock); spinlock_release(&session->ses_lock);
} }
} }
else else
{ {
spinlock_release(&session->ses_lock); spinlock_release(&session->ses_lock);
} }
}
return 1; return 1;
} }