Added missing spinlock_release to dcb_add_to_zombieslist to avoid deadlock.

This commit is contained in:
vraatikka
2013-09-08 23:24:54 +03:00
parent 66e9be814b
commit 03fed73b64

View File

@ -161,6 +161,7 @@ dcb_add_to_zombieslist(DCB *dcb)
if (dcb->state == DCB_STATE_ZOMBIE) if (dcb->state == DCB_STATE_ZOMBIE)
{ {
ss_dassert(zombies != NULL); ss_dassert(zombies != NULL);
spinlock_release(&zombiespin);
return; return;
} }
@ -216,7 +217,7 @@ static void
dcb_final_free(DCB *dcb) dcb_final_free(DCB *dcb)
{ {
SERVICE *service; SERVICE *service;
void* rsession = NULL;
CHK_DCB(dcb); CHK_DCB(dcb);
ss_info_dassert(dcb->state == DCB_STATE_DISCONNECTED, ss_info_dassert(dcb->state == DCB_STATE_DISCONNECTED,
"dcb not in DCB_STATE_DISCONNECTED state."); "dcb not in DCB_STATE_DISCONNECTED state.");
@ -255,15 +256,12 @@ SERVICE *service;
service->router != NULL && service->router != NULL &&
dcb->session->router_session != NULL) dcb->session->router_session != NULL)
{ {
void* rsession = NULL;
/** /**
* Protect call of closeSession. * Protect call of closeSession.
*/ */
spinlock_acquire(&dcb->session->ses_lock); spinlock_acquire(&dcb->session->ses_lock);
rsession = dcb->session->router_session; rsession = dcb->session->router_session;
dcb->session->router_session = NULL;
spinlock_release(&dcb->session->ses_lock); spinlock_release(&dcb->session->ses_lock);
if (rsession != NULL) { if (rsession != NULL) {
service->router->closeSession( service->router->closeSession(
service->router_instance, service->router_instance,
@ -283,13 +281,8 @@ SERVICE *service;
SESSION *local_session = dcb->session; SESSION *local_session = dcb->session;
dcb->session = NULL; dcb->session = NULL;
session_free(local_session); session_free(local_session);
skygw_log_write_flush(
LOGFILE_TRACE,
"%lu [dcb_final_free] DCB %p freed session %p",
pthread_self(),
dcb,
local_session);
} }
if (dcb->protocol) if (dcb->protocol)
free(dcb->protocol); free(dcb->protocol);
if (dcb->data) if (dcb->data)
@ -305,7 +298,7 @@ SERVICE *service;
* *
* This routine is called by each of the polling threads with * This routine is called by each of the polling threads with
* the thread id of the polling thread. It must clear the bit in * the thread id of the polling thread. It must clear the bit in
* the memdata btmask for the polling thread that calls it. If the * the memdata bitmask for the polling thread that calls it. If the
* operation of clearing this bit means that no bits are set in * operation of clearing this bit means that no bits are set in
* the memdata.bitmask then the DCB is no longer able to be * the memdata.bitmask then the DCB is no longer able to be
* referenced and it can be finally removed. * referenced and it can be finally removed.
@ -486,7 +479,7 @@ int eno = 0;
errno = 0; errno = 0;
skygw_log_write( skygw_log_write(
LOGFILE_ERROR, LOGFILE_ERROR,
"%lu [dcb_read] Setting FIONREAD for fd %d failed. " "%lu [dcb_read] ioctl FIONREAD for fd %d failed. "
"errno %d, %s. dcb->state = %d", "errno %d, %s. dcb->state = %d",
pthread_self(), pthread_self(),
dcb->fd, dcb->fd,
@ -526,7 +519,7 @@ int eno = 0;
skygw_log_write( skygw_log_write(
LOGFILE_TRACE, LOGFILE_TRACE,
"%lu [dcb_read] Read %d Bytes from fd %d", "%lu [dcb_read] Read %d bytes from fd %d",
pthread_self(), pthread_self(),
n, n,
dcb->fd); dcb->fd);
@ -541,7 +534,7 @@ int eno = 0;
errno = 0; errno = 0;
skygw_log_write( skygw_log_write(
LOGFILE_ERROR, LOGFILE_ERROR,
"%lu [dcb_read] Setting FIONREAD for fd %d failed. " "%lu [dcb_read] ioctl FIONREAD for fd %d failed. "
"errno %d, %s. dcb->state = %d", "errno %d, %s. dcb->state = %d",
pthread_self(), pthread_self(),
dcb->fd, dcb->fd,
@ -551,7 +544,6 @@ int eno = 0;
return -1; return -1;
} }
} /**< while (b>0) */ } /**< while (b>0) */
return n; return n;
} }
@ -717,10 +709,20 @@ int saved_errno = 0;
} }
/** /**
* Close a DCB * @node Removes dcb from poll set, and adds it to zombies list. As a consequense,
* dcb first moves to DCB_STATE_NOPOLLING, and then to DCB_STATE_ZOMBIE state.
* At the end of the function state may not be DCB_STATE_ZOMBIE because once dcb_initlock
* is released parallel threads may change the state.
*
* Parameters:
* @param dcb - <usage>
* <description>
*
* @return
*
*
* @details (write detailed description here)
* *
* Generic, non-protocol specific close funcitonality
* @param dcb The DCB to close
*/ */
void void
dcb_close(DCB *dcb) dcb_close(DCB *dcb)
@ -746,19 +748,8 @@ dcb_close(DCB *dcb)
prev_state == DCB_STATE_ZOMBIE, prev_state == DCB_STATE_ZOMBIE,
"Invalid state transition."); "Invalid state transition.");
} }
spinlock_release(&dcb->dcb_initlock); spinlock_release(&dcb->dcb_initlock);
if (succp) {
skygw_log_write(
LOGFILE_TRACE,
"%lu [dcb_close] Removed dcb %p in state %s from "
"poll set.",
pthread_self(),
dcb,
STRDCBSTATE(dcb->state));
}
if (dcb->state == DCB_STATE_NOPOLLING) { if (dcb->state == DCB_STATE_NOPOLLING) {
dcb_add_to_zombieslist(dcb); dcb_add_to_zombieslist(dcb);
} }