diff options
author | enal@chromium.org <enal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-05 02:25:02 +0000 |
---|---|---|
committer | enal@chromium.org <enal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-05 02:25:02 +0000 |
commit | 9faa065eed72e1a816c94b0764135ee0a1bcfb7a (patch) | |
tree | 91b63267ac56a599ae861839be6bd623a65abbbf | |
parent | c104a8966ef3e260f84f85840fa1c69501224cac (diff) | |
download | chromium_src-9faa065eed72e1a816c94b0764135ee0a1bcfb7a.zip chromium_src-9faa065eed72e1a816c94b0764135ee0a1bcfb7a.tar.gz chromium_src-9faa065eed72e1a816c94b0764135ee0a1bcfb7a.tar.bz2 |
Fix race condition (bug 108685).
In the ~AudioOutputController() we were calling method supposed to be run
on the audio manager message loop only.
BUG=108685
TEST=Should not be noticeable, crash should go away.
Review URL: http://codereview.chromium.org/9085030
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@116441 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | media/audio/audio_output_controller.cc | 43 | ||||
-rw-r--r-- | media/audio/audio_output_controller.h | 9 |
2 files changed, 38 insertions, 14 deletions
diff --git a/media/audio/audio_output_controller.cc b/media/audio/audio_output_controller.cc index d3cca44..4eb0556 100644 --- a/media/audio/audio_output_controller.cc +++ b/media/audio/audio_output_controller.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,10 +7,12 @@ #include "base/bind.h" #include "base/debug/trace_event.h" #include "base/message_loop.h" +#include "base/synchronization/waitable_event.h" #include "base/threading/platform_thread.h" #include "base/time.h" using base::Time; +using base::WaitableEvent; namespace media { @@ -40,7 +42,18 @@ AudioOutputController::AudioOutputController(AudioManager* audio_manager, AudioOutputController::~AudioOutputController() { DCHECK_EQ(kClosed, state_); - StopCloseAndClearStream(); + if (message_loop_ == MessageLoop::current()) { + DoStopCloseAndClearStream(NULL); + } else { + DCHECK(message_loop_); + WaitableEvent completion(true /* manual reset */, + false /* initial state */); + message_loop_->PostTask(FROM_HERE, + base::Bind(&AudioOutputController::DoStopCloseAndClearStream, + base::Unretained(this), + &completion)); + completion.Wait(); + } } // static @@ -139,7 +152,7 @@ void AudioOutputController::DoCreate(const AudioParameters& params) { return; DCHECK_EQ(kEmpty, state_); - StopCloseAndClearStream(); + DoStopCloseAndClearStream(NULL); stream_ = audio_manager_->MakeAudioOutputStreamProxy(params); if (!stream_) { // TODO(hclam): Define error types. @@ -148,7 +161,7 @@ void AudioOutputController::DoCreate(const AudioParameters& params) { } if (!stream_->Open()) { - StopCloseAndClearStream(); + DoStopCloseAndClearStream(NULL); // TODO(hclam): Define error types. handler_->OnError(this, 0); @@ -286,7 +299,7 @@ void AudioOutputController::DoClose(const base::Closure& closed_task) { DCHECK_EQ(message_loop_, MessageLoop::current()); if (state_ != kClosed) { - StopCloseAndClearStream(); + DoStopCloseAndClearStream(NULL); if (LowLatencyMode()) { sync_reader_->Close(); @@ -400,14 +413,20 @@ void AudioOutputController::SubmitOnMoreData_Locked() { handler_->OnMoreData(this, buffers_state); } -void AudioOutputController::StopCloseAndClearStream() { +void AudioOutputController::DoStopCloseAndClearStream(WaitableEvent *done) { + DCHECK_EQ(message_loop_, MessageLoop::current()); + // Allow calling unconditionally and bail if we don't have a stream_ to close. - if (!stream_) - return; - stream_->Stop(); - stream_->Close(); - stream_ = NULL; - weak_this_.InvalidateWeakPtrs(); + if (stream_ != NULL) { + stream_->Stop(); + stream_->Close(); + stream_ = NULL; + weak_this_.InvalidateWeakPtrs(); + } + + // Should be last in the method, do not touch "this" from here on. + if (done != NULL) + done->Signal(); } } // namespace media diff --git a/media/audio/audio_output_controller.h b/media/audio/audio_output_controller.h index 5234f58..274b5d3 100644 --- a/media/audio/audio_output_controller.h +++ b/media/audio/audio_output_controller.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -16,6 +16,10 @@ #include "media/audio/audio_manager.h" #include "media/audio/simple_sources.h" +namespace base { +class WaitableEvent; +} // namespace base + class MessageLoop; // An AudioOutputController controls an AudioOutputStream and provides data @@ -220,7 +224,8 @@ class MEDIA_EXPORT AudioOutputController void StartStream(); // Helper method that stops, closes, and NULLs |*stream_|. - void StopCloseAndClearStream(); + // Signals event when done if it is not NULL. + void DoStopCloseAndClearStream(base::WaitableEvent *done); scoped_refptr<AudioManager> audio_manager_; // |handler_| may be called only if |state_| is not kClosed. |