=?UTF-8?Q?J=C3=B6rg=20H=C3=B6hle=20?=: winmm: Make midiStream* messages asynchronous to avoid deadlocks.
Alexandre Julliard
julliard at winehq.org
Fri Feb 17 11:32:49 CST 2012
Module: wine
Branch: master
Commit: 21e47e905e2d1f1206344a83e303610d4992be05
URL: http://source.winehq.org/git/wine.git/?a=commit;h=21e47e905e2d1f1206344a83e303610d4992be05
Author: Jörg Höhle <hoehle at users.sourceforge.net>
Date: Tue Feb 7 23:10:03 2012 +0100
winmm: Make midiStream* messages asynchronous to avoid deadlocks.
---
dlls/winmm/winmm.c | 46 ++++++++++++++++++++--------------------------
1 files changed, 20 insertions(+), 26 deletions(-)
diff --git a/dlls/winmm/winmm.c b/dlls/winmm/winmm.c
index cb6292a..714a84e 100644
--- a/dlls/winmm/winmm.c
+++ b/dlls/winmm/winmm.c
@@ -1013,14 +1013,15 @@ static BOOL MMSYSTEM_MidiStream_MessageHandler(WINE_MIDIStream* lpMidiStrm, LPWI
for (;;) {
switch (msg->message) {
case WM_QUIT:
- SetEvent(lpMidiStrm->hEvent);
return FALSE;
case WINE_MSM_STOP:
TRACE("STOP\n");
/* this is not quite what MS doc says... */
midiOutReset(lpMidiStrm->hDevice);
/* empty list of already submitted buffers */
- for (lpMidiHdr = lpMidiStrm->lpMidiHdr; lpMidiHdr; ) {
+ lpMidiHdr = lpMidiStrm->lpMidiHdr;
+ lpMidiStrm->lpMidiHdr = NULL;
+ while (lpMidiHdr) {
LPMIDIHDR lphdr = lpMidiHdr;
lpMidiHdr = lpMidiHdr->lpNext;
lphdr->dwFlags |= MHDR_DONE;
@@ -1030,18 +1031,14 @@ static BOOL MMSYSTEM_MidiStream_MessageHandler(WINE_MIDIStream* lpMidiStrm, LPWI
(HDRVR)lpMidiStrm->hDevice, MM_MOM_DONE,
lpwm->mod.dwInstance, (DWORD_PTR)lphdr, 0);
}
- lpMidiStrm->lpMidiHdr = 0;
- SetEvent(lpMidiStrm->hEvent);
return TRUE;
case WINE_MSM_RESUME:
/* FIXME: send out cc64 0 (turn off sustain pedal) on every channel */
lpMidiStrm->dwStartTicks = GetTickCount() - lpMidiStrm->dwPositionMS;
- SetEvent(lpMidiStrm->hEvent);
return TRUE;
case WINE_MSM_PAUSE:
/* FIXME: send out cc64 0 (turn off sustain pedal) on every channel */
paused = TRUE;
- SetEvent(lpMidiStrm->hEvent);
break;
/* FIXME(EPP): "I don't understand the content of the first MIDIHDR sent
* by native mcimidi, it doesn't look like a correct one".
@@ -1248,25 +1245,12 @@ the_end:
}
/**************************************************************************
- * MMSYSTEM_MidiStream_PostMessage [internal]
- */
-static BOOL MMSYSTEM_MidiStream_PostMessage(WINE_MIDIStream* lpMidiStrm, WORD msg, DWORD pmt1, DWORD pmt2)
-{
- if (PostThreadMessageA(lpMidiStrm->dwThreadID, msg, pmt1, pmt2)) {
- MsgWaitForMultipleObjects( 1, &lpMidiStrm->hEvent, FALSE, INFINITE, 0 );
- } else {
- ERR("bad PostThreadMessageA\n");
- return FALSE;
- }
- return TRUE;
-}
-
-/**************************************************************************
* midiStreamClose [WINMM.@]
*/
MMRESULT WINAPI midiStreamClose(HMIDISTRM hMidiStrm)
{
WINE_MIDIStream* lpMidiStrm;
+ MMRESULT ret = 0;
TRACE("(%p)!\n", hMidiStrm);
@@ -1274,9 +1258,19 @@ MMRESULT WINAPI midiStreamClose(HMIDISTRM hMidiStrm)
return MMSYSERR_INVALHANDLE;
midiStreamStop(hMidiStrm);
- MMSYSTEM_MidiStream_PostMessage(lpMidiStrm, WM_QUIT, 0, 0);
+ PostThreadMessageA(lpMidiStrm->dwThreadID, WM_QUIT, 0, 0);
CloseHandle(lpMidiStrm->hEvent);
- HeapFree(GetProcessHeap(), 0, lpMidiStrm);
+ if (lpMidiStrm->hThread) {
+ if (GetCurrentThreadId() != lpMidiStrm->dwThreadID)
+ WaitForSingleObject(lpMidiStrm->hThread, INFINITE);
+ else {
+ FIXME("leak from call within function callback\n");
+ ret = MMSYSERR_HANDLEBUSY; /* yet don't signal it to app */
+ }
+ CloseHandle(lpMidiStrm->hThread);
+ }
+ if(!ret)
+ HeapFree(GetProcessHeap(), 0, lpMidiStrm);
return midiOutClose((HMIDIOUT)hMidiStrm);
}
@@ -1347,7 +1341,7 @@ MMRESULT WINAPI midiStreamOpen(HMIDISTRM* lphMidiStrm, LPUINT lpuDeviceID,
/* wait for thread to have started, and for its queue to be created */
WaitForSingleObject(lpMidiStrm->hEvent, INFINITE);
- MMSYSTEM_MidiStream_PostMessage(lpMidiStrm, WINE_MSM_PAUSE, 0, 0);
+ PostThreadMessageA(lpMidiStrm->dwThreadID, WINE_MSM_PAUSE, 0, 0);
TRACE("=> (%u/%d) hMidi=%p ret=%d lpMidiStrm=%p\n",
*lpuDeviceID, lpwm->mld.uDeviceID, *lphMidiStrm, ret, lpMidiStrm);
@@ -1405,7 +1399,7 @@ MMRESULT WINAPI midiStreamPause(HMIDISTRM hMidiStrm)
if (!MMSYSTEM_GetMidiStream(hMidiStrm, &lpMidiStrm, NULL))
return MMSYSERR_INVALHANDLE;
- MMSYSTEM_MidiStream_PostMessage(lpMidiStrm, WINE_MSM_PAUSE, 0, 0);
+ PostThreadMessageA(lpMidiStrm->dwThreadID, WINE_MSM_PAUSE, 0, 0);
return ret;
}
@@ -1501,7 +1495,7 @@ MMRESULT WINAPI midiStreamRestart(HMIDISTRM hMidiStrm)
if (!MMSYSTEM_GetMidiStream(hMidiStrm, &lpMidiStrm, NULL))
return MMSYSERR_INVALHANDLE;
- MMSYSTEM_MidiStream_PostMessage(lpMidiStrm, WINE_MSM_RESUME, 0, 0);
+ PostThreadMessageA(lpMidiStrm->dwThreadID, WINE_MSM_RESUME, 0, 0);
return ret;
}
@@ -1517,7 +1511,7 @@ MMRESULT WINAPI midiStreamStop(HMIDISTRM hMidiStrm)
if (!MMSYSTEM_GetMidiStream(hMidiStrm, &lpMidiStrm, NULL))
return MMSYSERR_INVALHANDLE;
- MMSYSTEM_MidiStream_PostMessage(lpMidiStrm, WINE_MSM_STOP, 0, 0);
+ PostThreadMessageA(lpMidiStrm->dwThreadID, WINE_MSM_STOP, 0, 0);
return ret;
}
More information about the wine-cvs
mailing list