summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhenrika@chromium.org <henrika@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-01 11:14:50 +0000
committerhenrika@chromium.org <henrika@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-01 11:14:50 +0000
commit9055ba2bd5d4da411438f36dd49617bd4edd0ac8 (patch)
treef9ad17f4befd6ab9fe7485d4b61d4c88569556be
parent9986e3cd61a6bb80fc9e770cd6e8507177a27a12 (diff)
downloadchromium_src-9055ba2bd5d4da411438f36dd49617bd4edd0ac8.zip
chromium_src-9055ba2bd5d4da411438f36dd49617bd4edd0ac8.tar.gz
chromium_src-9055ba2bd5d4da411438f36dd49617bd4edd0ac8.tar.bz2
Avoids crash in PCMWaveInAudioInputStream::WaveCallback
BUG=12092064 TEST= Review URL: https://codereview.chromium.org/12092064 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@180125 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--media/audio/win/wavein_input_win.cc22
-rw-r--r--media/audio/win/wavein_input_win.h4
2 files changed, 22 insertions, 4 deletions
diff --git a/media/audio/win/wavein_input_win.cc b/media/audio/win/wavein_input_win.cc
index a625707..68d5265 100644
--- a/media/audio/win/wavein_input_win.cc
+++ b/media/audio/win/wavein_input_win.cc
@@ -152,6 +152,7 @@ void PCMWaveInAudioInputStream::Stop() {
HandleError(::GetLastError());
return;
}
+
// Stop is always called before Close. In case of error, this will be
// also called when closing the input controller.
manager_->DecreaseActiveInputStreamCount();
@@ -163,6 +164,13 @@ void PCMWaveInAudioInputStream::Stop() {
HandleError(res);
return;
}
+
+ // Wait for lock to ensure all outstanding callbacks have completed.
+ base::AutoLock auto_lock(lock_);
+
+ // Don't use callback after Stop().
+ callback_ = NULL;
+
state_ = kStateReady;
}
@@ -265,6 +273,9 @@ void PCMWaveInAudioInputStream::WaveCallback(HWAVEIN hwi, UINT msg,
PCMWaveInAudioInputStream* obj =
reinterpret_cast<PCMWaveInAudioInputStream*>(instance);
+ // The lock ensures that Stop() can't be called during a callback.
+ base::AutoLock auto_lock(obj->lock_);
+
if (msg == WIM_DATA) {
// WIM_DONE indicates that the driver is done with our buffer. We pass it
// to the callback and check if we need to stop playing.
@@ -273,10 +284,13 @@ void PCMWaveInAudioInputStream::WaveCallback(HWAVEIN hwi, UINT msg,
// TODO(henrika): the |volume| parameter is always set to zero since there
// is currently no support for controlling the microphone volume level.
WAVEHDR* buffer = reinterpret_cast<WAVEHDR*>(param1);
- obj->callback_->OnData(obj, reinterpret_cast<const uint8*>(buffer->lpData),
- buffer->dwBytesRecorded,
- buffer->dwBytesRecorded,
- 0.0);
+ if (obj->callback_) {
+ obj->callback_->OnData(obj,
+ reinterpret_cast<const uint8*>(buffer->lpData),
+ buffer->dwBytesRecorded,
+ buffer->dwBytesRecorded,
+ 0.0);
+ }
if (obj->state_ == kStateStopping) {
// The main thread has called Stop() and is waiting to issue waveOutReset
diff --git a/media/audio/win/wavein_input_win.h b/media/audio/win/wavein_input_win.h
index 82f1f55..076b099 100644
--- a/media/audio/win/wavein_input_win.h
+++ b/media/audio/win/wavein_input_win.h
@@ -12,6 +12,7 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
+#include "base/synchronization/lock.h"
#include "base/win/scoped_handle.h"
#include "media/audio/audio_io.h"
#include "media/audio/audio_parameters.h"
@@ -116,6 +117,9 @@ class PCMWaveInAudioInputStream : public AudioInputStream {
// An event that is signaled when the callback thread is ready to stop.
base::win::ScopedHandle stopped_event_;
+ // Lock used to avoid conflicts when Stop() is called during a callback.
+ base::Lock lock_;
+
DISALLOW_COPY_AND_ASSIGN(PCMWaveInAudioInputStream);
};