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

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


Hi,

please try and convince me that a deadlock cannot happen.

http://source.winehq.org/source//dlls/winealsa.drv/mmdevdrv.c

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

The callback invokes
alsa_push_buffer_data()
 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.

Regards,
 Jörg Höhle


More information about the wine-devel mailing list