Fix to bugs #665, and #664. Potentially to #649.

http://bugs.skysql.com/show_bug.cgi?id=665
http://bugs.skysql.com/show_bug.cgi?id=664
http://bugs.skysql.com/show_bug.cgi?id=649

dcb.c:dcb_final_free: (665):set dcb->session->client pointer to NULL so that it won't be read anymore and other threads won't try to close it.
	dcb_final_free:(664):don't free dcb->data, it is either freed in session_alloc if session creation fails or in session_free only.
session.c:if session creation fails, free dcb->data and remove links between client DCB and session.
mysql_backend.c:(665):gw_backend_close:check that session->client isn't NULL and that client DCB's state is still polling before calling dcb_close for it.
mysql_client.c:gw_mysql_do_authentication:if anything fails, and session_alloc won't be called, free dcb->data.
mysql_common.c:gw_send_authentication_to_backend:if session is already closing then return with error.
This commit is contained in:
VilhoRaatikka
2014-12-29 20:19:01 +02:00
parent beacd524da
commit 635fcf708f
8 changed files with 97 additions and 29 deletions

View File

@ -699,16 +699,6 @@ gw_MySQLWrite_backend(DCB *dcb, GWBUF *queue)
switch (backend_protocol->protocol_auth_state) {
case MYSQL_HANDSHAKE_FAILED:
case MYSQL_AUTH_FAILED:
{
size_t len;
char* str;
uint8_t* packet = (uint8_t *)queue->start;
uint8_t* startpoint;
len = (size_t)MYSQL_GET_PACKET_LEN(packet);
startpoint = &packet[5];
str = (char *)malloc(len+1);
snprintf(str, len+1, "%s", startpoint);
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : Unable to write to backend due to "
@ -717,13 +707,11 @@ gw_MySQLWrite_backend(DCB *dcb, GWBUF *queue)
while ((queue = gwbuf_consume(
queue,
GWBUF_LENGTH(queue))) != NULL);
free(str);
rc = 0;
spinlock_release(&dcb->authlock);
goto return_rc;
break;
}
case MYSQL_IDLE:
{
uint8_t* ptr = GWBUF_DATA(queue);
@ -1166,21 +1154,33 @@ gw_backend_close(DCB *dcb)
mysql_protocol_done(dcb);
spinlock_acquire(&session->ses_lock);
/**
* If session->state is STOPPING, start closing client session.
* Otherwise only this backend connection is closed.
*/
if (session != NULL && session->state == SESSION_STATE_STOPPING)
if (session != NULL &&
session->state == SESSION_STATE_STOPPING &&
session->client != NULL)
{
client_dcb = session->client;
if (client_dcb != NULL &&
client_dcb->state == DCB_STATE_POLLING)
if (client_dcb->state == DCB_STATE_POLLING)
{
spinlock_release(&session->ses_lock);
/** Close client DCB */
dcb_close(client_dcb);
}
else
{
spinlock_release(&session->ses_lock);
}
}
else
{
spinlock_release(&session->ses_lock);
}
return 1;
}