=?UTF-8?Q?J=C3=B6rg=20H=C3=B6hle=20?=: winecoreaudio: Avoid deadlock in AudioClient_Stop.

Alexandre Julliard julliard at winehq.org
Tue Jan 31 14:06:19 CST 2012


Module: wine
Branch: master
Commit: c99501197425ca0bbda04465da0c23ea76fe73a7
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=c99501197425ca0bbda04465da0c23ea76fe73a7

Author: Jörg Höhle <hoehle at 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);




More information about the wine-cvs mailing list