winpr/synch: fix timerqueue segfault

The current experimental/incomplete WinPR timer queue implementation
has several race conditions.
This commit fixes a segfault caused by not unklinking freed timers
from the timer queue timers list.
This commit is contained in:
Norbert Federa 2016-06-06 13:18:00 +02:00
parent 8c4f3ba165
commit e35049c20e

View File

@ -641,13 +641,18 @@ BOOL DeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent)
pthread_mutex_unlock(&(timerQueue->cond_mutex));
pthread_join(timerQueue->thread, &rvalue);
if (CompletionEvent == INVALID_HANDLE_VALUE)
/**
* Quote from MSDN regarding CompletionEvent:
* If this parameter is INVALID_HANDLE_VALUE, the function waits for
* all callback functions to complete before returning.
* If this parameter is NULL, the function marks the timer for
* deletion and returns immediately.
*
* Note: The current WinPR implementation implicitly waits for any
* callback functions to complete (see pthread_join above)
*/
{
/* Wait for all callback functions to complete before returning */
}
else
{
/* Cancel all timers and return immediately */
/* Move all active timers to the inactive timer list */
node = timerQueue->activeHead;
@ -765,15 +770,18 @@ BOOL DeleteTimerQueueTimer(HANDLE TimerQueue, HANDLE Timer, HANDLE CompletionEve
timer = (WINPR_TIMER_QUEUE_TIMER*) Timer;
pthread_mutex_lock(&(timerQueue->cond_mutex));
if (CompletionEvent == INVALID_HANDLE_VALUE)
{
/* Wait for all callback functions to complete before returning */
}
else
{
/* Cancel timer and return immediately */
RemoveTimerQueueTimer(&(timerQueue->activeHead), timer);
}
/**
* Quote from MSDN regarding CompletionEvent:
* If this parameter is INVALID_HANDLE_VALUE, the function waits for
* all callback functions to complete before returning.
* If this parameter is NULL, the function marks the timer for
* deletion and returns immediately.
*
* Note: The current WinPR implementation implicitly waits for any
* callback functions to complete (see cond_mutex usage)
*/
RemoveTimerQueueTimer(&(timerQueue->activeHead), timer);
pthread_cond_signal(&(timerQueue->cond));
pthread_mutex_unlock(&(timerQueue->cond_mutex));