Jörg Höhle : winealsa: Avoid deadlock in AudioClient_Stop.

Alexandre Julliard julliard at winehq.org
Tue Jun 21 12:25:41 CDT 2011


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

Author: Jörg Höhle <hoehle at users.sourceforge.net>
Date:   Thu Jun 16 00:37:59 2011 +0200

winealsa: Avoid deadlock in AudioClient_Stop.

---

 dlls/winealsa.drv/mmdevdrv.c |   26 +++++++++++++++++++-------
 1 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/dlls/winealsa.drv/mmdevdrv.c b/dlls/winealsa.drv/mmdevdrv.c
index abb2d39..236ae40 100644
--- a/dlls/winealsa.drv/mmdevdrv.c
+++ b/dlls/winealsa.drv/mmdevdrv.c
@@ -1472,13 +1472,15 @@ static void CALLBACK alsa_push_buffer_data(void *user, BOOLEAN timer)
 
     EnterCriticalSection(&This->lock);
 
-    if(This->dataflow == eRender && This->held_frames)
-        alsa_write_data(This);
-    else if(This->dataflow == eCapture)
-        alsa_read_data(This);
+    if(This->started){
+        if(This->dataflow == eRender && This->held_frames)
+            alsa_write_data(This);
+        else if(This->dataflow == eCapture)
+            alsa_read_data(This);
 
-    if(This->event)
-        SetEvent(This->event);
+        if(This->event)
+            SetEvent(This->event);
+    }
 
     LeaveCriticalSection(&This->lock);
 }
@@ -1567,6 +1569,8 @@ static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface)
 {
     ACImpl *This = impl_from_IAudioClient(iface);
     int err;
+    HANDLE event;
+    BOOL wait;
 
     TRACE("(%p)\n", This);
 
@@ -1582,7 +1586,11 @@ static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface)
         return S_FALSE;
     }
 
-    DeleteTimerQueueTimer(g_timer_q, This->timer, INVALID_HANDLE_VALUE);
+    event = CreateEventW(NULL, TRUE, FALSE, NULL);
+    wait = !DeleteTimerQueueTimer(g_timer_q, This->timer, event);
+    if(wait)
+        WARN("DeleteTimerQueueTimer error %u\n", GetLastError());
+    wait = wait && GetLastError() == ERROR_IO_PENDING;
 
     if((err = snd_pcm_drop(This->pcm_handle)) < 0){
         LeaveCriticalSection(&This->lock);
@@ -1600,6 +1608,10 @@ static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface)
 
     LeaveCriticalSection(&This->lock);
 
+    if(event && wait)
+        WaitForSingleObject(event, INFINITE);
+    CloseHandle(event);
+
     return S_OK;
 }
 




More information about the wine-cvs mailing list