Jörg Höhle : winecoreaudio: Avoid deadlock in AudioClient_Stop.
Module: wine Branch: master Commit: c99501197425ca0bbda04465da0c23ea76fe73a7 URL: http://source.winehq.org/git/wine.git/?a=commit;h=c99501197425ca0bbda04465da... Author: Jörg Höhle <hoehle(a)users.sourceforge.net> Date: Sun Jan 15 20:16:51 2012 +0100 winecoreaudio: Avoid deadlock in AudioClient_Stop. --- dlls/winecoreaudio.drv/mmdevdrv.c | 22 ++++++++++++++++++---- 1 files changed, 18 insertions(+), 4 deletions(-) diff --git a/dlls/winecoreaudio.drv/mmdevdrv.c b/dlls/winecoreaudio.drv/mmdevdrv.c index 07359c0..52fdef0 100644 --- a/dlls/winecoreaudio.drv/mmdevdrv.c +++ b/dlls/winecoreaudio.drv/mmdevdrv.c @@ -1440,8 +1440,12 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient *iface) if(This->event) if(!CreateTimerQueueTimer(&This->timer, g_timer_q, - ca_period_cb, This, 0, This->period_ms, 0)) - ERR("Unable to create timer: %u\n", GetLastError()); + ca_period_cb, This, 0, This->period_ms, 0)){ + This->timer = NULL; + OSSpinLockUnlock(&This->lock); + WARN("Unable to create timer: %u\n", GetLastError()); + return E_OUTOFMEMORY; + } This->playing = StateInTransition; @@ -1467,6 +1471,8 @@ static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface) ACImpl *This = impl_from_IAudioClient(iface); AudioTimeStamp tstamp; OSStatus sc; + HANDLE event = NULL; + BOOL wait = FALSE; TRACE("(%p)\n", This); @@ -1487,9 +1493,13 @@ static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface) return S_OK; } - if(This->timer && This->timer != INVALID_HANDLE_VALUE){ - DeleteTimerQueueTimer(g_timer_q, This->timer, INVALID_HANDLE_VALUE); + if(This->timer){ + event = CreateEventW(NULL, TRUE, FALSE, NULL); + wait = !DeleteTimerQueueTimer(g_timer_q, This->timer, event); This->timer = NULL; + if(wait) + WARN("DeleteTimerQueueTimer error %u\n", GetLastError()); + wait = wait && GetLastError() == ERROR_IO_PENDING; } This->playing = StateInTransition; @@ -1506,6 +1516,10 @@ static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface) OSSpinLockUnlock(&This->lock); + if(event && wait) + WaitForSingleObject(event, INFINITE); + CloseHandle(event); + sc = AudioQueueFlush(This->aqueue); if(sc != noErr) WARN("Unable to flush audio queue: %lx\n", sc);
participants (1)
-
Alexandre Julliard