deadlock in mmdevapi AudioClient_Stop (winealsa.drv/mmdevdrv.c)

Joerg-Cyril.Hoehle at Joerg-Cyril.Hoehle at
Wed Jun 15 03:00:37 CDT 2011


please try and convince me that a deadlock cannot happen.

AudioClient_Start calls
   which creates a new thread periodically invoking the timer callback.

The callback invokes
 which ceases the audio client object lock (This->lock).

 AudioClient_Stop performs
  EnterCriticalSection(&This->lock); then
  DeleteTimerQueueTimer(g_timer_q, This->timer, INVALID_HANDLE_VALUE);

Now imagine Stop is invoked, EnterCriticalSection executed then the thread is preempted.
Suppose the timer callback kicks in: alsa_push_buffer_data will block on This->lock.
When the thread is resumed, DeleteTimerQueue will hang forever waiting for all timer callbacks to come to an end.

My opinion is that critical sections are great to prevent concurrent execution while
things are running, but they are hell to tear down properly.

IMHO, LeaveCriticalSection + Re-EnterCriticalSection around DeleteTimerQueue is not a solution.
I consider using Leave+EnterCS around anything that can wait/block an anti-pattern
(there are a few places like that in Wine). I believe a "restart op" is needed in general
(like a "restart transaction if it failed" in databases) as anything could have happened while waiting.

 Jörg Höhle

More information about the wine-devel mailing list