Module: wine Branch: master Commit: 06d705e7dfc3febfbf3592de942a3100dffde5b3 URL: http://source.winehq.org/git/wine.git/?a=commit;h=06d705e7dfc3febfbf3592de94...
Author: Ken Thomases ken@codeweavers.com Date: Sat Apr 11 07:18:23 2009 -0500
winecoreaudio: Avoid a race between closing and opening the waveOut device.
---
dlls/winecoreaudio.drv/audio.c | 22 ++++++++++++++++------ 1 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/dlls/winecoreaudio.drv/audio.c b/dlls/winecoreaudio.drv/audio.c index e81aa3e..9b55326 100644 --- a/dlls/winecoreaudio.drv/audio.c +++ b/dlls/winecoreaudio.drv/audio.c @@ -105,6 +105,7 @@ AudioUnitRender( AudioUnit ci, #define WINE_WS_STOPPED 2 #define WINE_WS_CLOSED 3 #define WINE_WS_OPENING 4 +#define WINE_WS_CLOSING 5
typedef struct tagCoreAudio_Device { char dev_name[32]; @@ -957,14 +958,17 @@ static DWORD wodClose(WORD wDevID) } else { OSStatus err; + AudioUnit audioUnit = wwo->audioUnit; + /* sanity check: this should not happen since the device must have been reset before */ if (wwo->lpQueuePtr || wwo->lpPlayPtr) ERR("out of sync\n");
- wwo->state = WINE_WS_CLOSED; /* mark the device as closed */ + wwo->state = WINE_WS_CLOSING; /* mark the device as closing */ + wwo->audioUnit = NULL;
OSSpinLockUnlock(&wwo->lock);
- err = AudioUnitUninitialize(wwo->audioUnit); + err = AudioUnitUninitialize(audioUnit); if (err) { ERR("AudioUnitUninitialize return %c%c%c%c\n", (char) (err >> 24), (char) (err >> 16), @@ -973,12 +977,17 @@ static DWORD wodClose(WORD wDevID) return MMSYSERR_ERROR; /* FIXME return an error based on the OSStatus */ }
- if ( !AudioUnit_CloseAudioUnit(wwo->audioUnit) ) + if ( !AudioUnit_CloseAudioUnit(audioUnit) ) { ERR("Can't close AudioUnit\n"); return MMSYSERR_ERROR; /* FIXME return an error based on the OSStatus */ }
+ OSSpinLockLock(&wwo->lock); + assert(wwo->state == WINE_WS_CLOSING); + wwo->state = WINE_WS_CLOSED; /* mark the device as closed */ + OSSpinLockUnlock(&wwo->lock); + ret = wodNotifyClient(wwo, WOM_CLOSE, 0L, 0L); }
@@ -1332,7 +1341,8 @@ static DWORD wodReset(WORD wDevID)
OSSpinLockLock(&wwo->lock);
- if (wwo->state == WINE_WS_CLOSED || wwo->state == WINE_WS_OPENING) + if (wwo->state == WINE_WS_CLOSED || wwo->state == WINE_WS_CLOSING || + wwo->state == WINE_WS_OPENING) { OSSpinLockUnlock(&wwo->lock); WARN("resetting a closed device\n"); @@ -1631,8 +1641,8 @@ OSStatus CoreAudio_woAudioUnitIOProc(void *inRefCon, OSSpinLockLock(&wwo->lock);
/* We might have been called before wwo has been completely filled out by - * wodOpen. We have to do nothing in that case. The check of wwo->state - * below ensures that. */ + * wodOpen, or while it's being closed in wodClose. We have to do nothing + * in that case. The check of wwo->state below ensures that. */ while (dataNeeded > 0 && wwo->state == WINE_WS_PLAYING && wwo->lpPlayPtr) { unsigned int available = wwo->lpPlayPtr->dwBufferLength - wwo->dwPartialOffset;