Lock writeq before inspecting it

Looking at the contents of the writeq should be done under a spinlock
otherwise it is possible that another thread grabs the queue.
This commit is contained in:
Markus Makela
2016-09-16 01:11:44 +03:00
parent 2a4addc298
commit 89f9f4a42f

View File

@ -1184,48 +1184,38 @@ static int gw_write_backend_event(DCB *dcb)
*/ */
if (dcb->state != DCB_STATE_POLLING) if (dcb->state != DCB_STATE_POLLING)
{ {
uint8_t* data; uint8_t* data = NULL;
bool com_quit = false;
if (dcb->writeq != NULL) spinlock_acquire(&dcb->writeqlock);
if (dcb->writeq)
{ {
data = (uint8_t *) GWBUF_DATA(dcb->writeq); data = (uint8_t *) GWBUF_DATA(dcb->writeq);
com_quit = MYSQL_IS_COM_QUIT(data);
rc = 0;
}
spinlock_release(&dcb->writeqlock);
if (dcb->session->client_dcb == NULL)
{
rc = 0;
}
else if (!(MYSQL_IS_COM_QUIT(data)))
{
/*< vraa : errorHandle */
mysql_send_custom_error(dcb->session->client_dcb,
1,
0,
"Writing to backend failed due invalid Maxscale "
"state.");
MXS_DEBUG("%lu [gw_write_backend_event] Write to backend "
"dcb %p fd %d "
"failed due invalid state %s.",
pthread_self(),
dcb,
dcb->fd,
STRDCBSTATE(dcb->state));
MXS_ERROR("Attempt to write buffered data to backend " if (data && !com_quit)
"failed " {
"due internal inconsistent state."); mysql_send_custom_error(dcb->session->client_dcb, 1, 0,
"Writing to backend failed due invalid Maxscale state.");
MXS_DEBUG("%lu [gw_write_backend_event] Write to backend "
"dcb %p fd %d failed due invalid state %s.",
pthread_self(), dcb, dcb->fd, STRDCBSTATE(dcb->state));
rc = 0; MXS_ERROR("Attempt to write buffered data to backend "
} "failed due internal inconsistent state.");
} }
else else
{ {
MXS_DEBUG("%lu [gw_write_backend_event] Dcb %p in state %s " MXS_DEBUG("%lu [gw_write_backend_event] Dcb %p in state %s "
"but there's nothing to write either.", "but there's nothing to write either.",
pthread_self(), pthread_self(), dcb, STRDCBSTATE(dcb->state));
dcb,
STRDCBSTATE(dcb->state));
rc = 1; rc = 1;
} }
goto return_rc; goto return_rc;
} }