From 6ffb9010811ee9bc0c3703716443c4dd00922f6f Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 25 Mar 2009 17:20:51 +0100 Subject: bugfix: potential abort with DA queue after high watermark is reached There exists a race condition that can lead to a segfault. Thanks go to vbernetr, who performed the analysis and provided patch, which I only tweaked a very little bit. --- runtime/wtp.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'runtime/wtp.c') diff --git a/runtime/wtp.c b/runtime/wtp.c index 8b041ea2..fcefa1d8 100644 --- a/runtime/wtp.c +++ b/runtime/wtp.c @@ -76,6 +76,7 @@ static rsRetVal NotImplementedDummy() { return RS_RET_OK; } */ BEGINobjConstruct(wtp) /* be sure to specify the object type also in END macro! */ pthread_mutex_init(&pThis->mut, NULL); + pthread_mutex_init(&pThis->mutThrdShutdwn, NULL); pthread_cond_init(&pThis->condThrdTrm, NULL); /* set all function pointers to "not implemented" dummy so that we can safely call them */ pThis->pfChkStopWrkr = NotImplementedDummy; @@ -140,6 +141,7 @@ CODESTARTobjDestruct(wtp) /* actual destruction */ pthread_cond_destroy(&pThis->condThrdTrm); pthread_mutex_destroy(&pThis->mut); + pthread_mutex_destroy(&pThis->mutThrdShutdwn); if(pThis->pszDbgHdr != NULL) free(pThis->pszDbgHdr); @@ -189,11 +191,23 @@ wtpProcessThrdChanges(wtp_t *pThis) if(pThis->bThrdStateChanged == 0) FINALIZE; - /* go through all threads */ - for(i = 0 ; i < pThis->iNumWorkerThreads ; ++i) { - wtiProcessThrdChanges(pThis->pWrkr[i], LOCK_MUTEX); + if(d_pthread_mutex_trylock(&(pThis->mutThrdShutdwn)) != 0) { + /* another thread is already in the loop */ + FINALIZE; } + do { + /* reset the change marker */ + pThis->bThrdStateChanged = 0; + /* go through all threads */ + for(i = 0 ; i < pThis->iNumWorkerThreads ; ++i) { + wtiProcessThrdChanges(pThis->pWrkr[i], LOCK_MUTEX); + } + /* restart if another change occured while we were processing the changes */ + } while(pThis->bThrdStateChanged != 0); + + d_pthread_mutex_unlock(&(pThis->mutThrdShutdwn)); + finalize_it: RETiRet; } -- cgit