Module: wine Branch: master Commit: c99501197425ca0bbda04465da0c23ea76fe73a7 URL: http://source.winehq.org/git/wine.git/?a=commit;h=c99501197425ca0bbda04465da...
Author: Jörg Höhle hoehle@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);