Always clear callback after WaveOut Stop().

If an error occurs after Stop() the callback may be destroyed, yet
the callback value was not cleared.  During Close() stop may be called
again, if an error occurs the free'd callback will be notified of the
error...

BUG=none
TEST=none

Review URL: https://codereview.chromium.org/115523010

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@243649 0039d316-1c4b-4281-b951-d872f2087c98
parent d9d59d9f
...@@ -248,39 +248,25 @@ void PCMWaveOutAudioOutputStream::Stop() { ...@@ -248,39 +248,25 @@ void PCMWaveOutAudioOutputStream::Stop() {
state_ = PCMA_STOPPING; state_ = PCMA_STOPPING;
base::subtle::MemoryBarrier(); base::subtle::MemoryBarrier();
// Stop watching for buffer event, wait till all the callbacks are complete. // Stop watching for buffer event, waits until outstanding callbacks finish.
// Should be done before ::waveOutReset() call to avoid race condition when
// callback that is currently active and already checked that stream is still
// being played calls ::waveOutWrite() after ::waveOutReset() returns, later
// causing ::waveOutClose() to fail with WAVERR_STILLPLAYING.
// TODO(enal): that delays actual stopping of playback. Alternative can be
// to call ::waveOutReset() twice, once before
// ::UnregisterWaitEx() and once after.
if (waiting_handle_) { if (waiting_handle_) {
if (!::UnregisterWaitEx(waiting_handle_, INVALID_HANDLE_VALUE)) { if (!::UnregisterWaitEx(waiting_handle_, INVALID_HANDLE_VALUE))
state_ = PCMA_PLAYING; HandleError(::GetLastError());
HandleError(MMSYSERR_ERROR);
return;
}
waiting_handle_ = NULL; waiting_handle_ = NULL;
} }
// Stop playback. // Stop playback.
MMRESULT res = ::waveOutReset(waveout_); MMRESULT res = ::waveOutReset(waveout_);
if (res != MMSYSERR_NOERROR) { if (res != MMSYSERR_NOERROR)
state_ = PCMA_PLAYING;
HandleError(res); HandleError(res);
return;
}
// Wait for lock to ensure all outstanding callbacks have completed. // Wait for lock to ensure all outstanding callbacks have completed.
base::AutoLock auto_lock(lock_); base::AutoLock auto_lock(lock_);
// waveOutReset() leaves buffers in the unpredictable state, causing // waveOutReset() leaves buffers in the unpredictable state, causing
// problems if we want to close, release, or reuse them. Fix the states. // problems if we want to close, release, or reuse them. Fix the states.
for (int ix = 0; ix != num_buffers_; ++ix) { for (int ix = 0; ix != num_buffers_; ++ix)
GetBuffer(ix)->dwFlags = WHDR_PREPARED; GetBuffer(ix)->dwFlags = WHDR_PREPARED;
}
// Don't use callback after Stop(). // Don't use callback after Stop().
callback_ = NULL; callback_ = NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment