Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(110)

Side by Side Diff: media/audio/audio_manager.cc

Issue 2784433002: Ensures that audio tasks cannot run after AudioManager is deleted. (Closed)
Patch Set: fixes content_browsertests and content_unittests Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/audio/audio_manager.h" 5 #include "media/audio/audio_manager.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <utility> 9 #include <utility>
10 10
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 DISALLOW_COPY_AND_ASSIGN(AudioManagerHelper); 234 DISALLOW_COPY_AND_ASSIGN(AudioManagerHelper);
235 }; 235 };
236 236
237 AudioManagerHelper* GetHelper() { 237 AudioManagerHelper* GetHelper() {
238 static AudioManagerHelper* helper = new AudioManagerHelper(); 238 static AudioManagerHelper* helper = new AudioManagerHelper();
239 return helper; 239 return helper;
240 } 240 }
241 241
242 } // namespace 242 } // namespace
243 243
244 void AudioManagerDeleter::operator()(const AudioManager* instance) const {
245 CHECK(instance);
246 // We reset g_last_created here instead of in the destructor of AudioManager
247 // because the destructor runs on the audio thread. We want to always change
248 // g_last_created from the main thread.
249 if (g_last_created == instance) {
250 g_last_created = nullptr;
251 } else {
252 // We create multiple instances of AudioManager only when testing.
253 // We should not encounter this case in production.
254 LOG(WARNING) << "Multiple instances of AudioManager detected";
255 }
256
257 #if defined(OS_MACOSX)
258 // If we are on Mac, tasks after this point are not executed, hence this is
259 // the only chance to delete the audio manager (which on Mac lives on the
260 // main browser thread instead of a dedicated audio thread). If we don't
261 // delete here, the CoreAudio thread can keep providing callbacks, which
262 // uses a state that is destroyed in ~BrowserMainLoop().
263 // See http://crbug.com/623703 for more details.
264 DCHECK(instance->GetTaskRunner()->BelongsToCurrentThread());
265 delete instance;
266 #else
267 // AudioManager must be destroyed on the audio thread.
268 if (!instance->GetTaskRunner()->DeleteSoon(FROM_HERE, instance)) {
269 LOG(WARNING) << "Failed to delete AudioManager instance.";
270 }
271 #endif
272 }
273
274 // Forward declaration of the platform specific AudioManager factory function. 244 // Forward declaration of the platform specific AudioManager factory function.
275 ScopedAudioManagerPtr CreateAudioManager( 245 std::unique_ptr<AudioManager> CreateAudioManager(
276 scoped_refptr<base::SingleThreadTaskRunner> task_runner, 246 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
277 scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner, 247 scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
278 AudioLogFactory* audio_log_factory); 248 AudioLogFactory* audio_log_factory);
279 249
280 void AudioManager::SetMaxStreamCountForTesting(int max_input, int max_output) { 250 void AudioManager::SetMaxStreamCountForTesting(int max_input, int max_output) {
281 NOTREACHED(); 251 NOTREACHED();
282 } 252 }
283 253
284 AudioManager::AudioManager( 254 AudioManager::AudioManager(
285 scoped_refptr<base::SingleThreadTaskRunner> task_runner, 255 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
286 scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner) 256 scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner)
287 : task_runner_(std::move(task_runner)), 257 : task_runner_(std::move(task_runner)),
288 worker_task_runner_(std::move(worker_task_runner)) { 258 worker_task_runner_(std::move(worker_task_runner)) {
289 DCHECK(task_runner_); 259 DCHECK(task_runner_);
290 DCHECK(worker_task_runner_); 260 DCHECK(worker_task_runner_);
291 261
292 if (g_last_created) { 262 if (g_last_created) {
293 // We create multiple instances of AudioManager only when testing. 263 // We create multiple instances of AudioManager only when testing.
294 // We should not encounter this case in production. 264 // We should not encounter this case in production.
295 LOG(WARNING) << "Multiple instances of AudioManager detected"; 265 LOG(WARNING) << "Multiple instances of AudioManager detected";
296 } 266 }
297 // We always override |g_last_created| irrespective of whether it is already 267 // We always override |g_last_created| irrespective of whether it is already
298 // set or not becuase it represents the last created instance. 268 // set or not becuase it represents the last created instance.
299 g_last_created = this; 269 g_last_created = this;
300 } 270 }
301 271
302 AudioManager::~AudioManager() { 272 AudioManager::~AudioManager() {
303 DCHECK(task_runner_->BelongsToCurrentThread()); 273 DCHECK(thread_checker_.CalledOnValidThread());
274
275 if (g_last_created == this) {
276 g_last_created = nullptr;
277 } else {
278 // We create multiple instances of AudioManager only when testing.
279 // We should not encounter this case in production.
280 LOG(WARNING) << "Multiple instances of AudioManager detected";
281 }
304 } 282 }
305 283
306 // static 284 // static
307 ScopedAudioManagerPtr AudioManager::Create( 285 std::unique_ptr<AudioManager> AudioManager::Create(
308 scoped_refptr<base::SingleThreadTaskRunner> task_runner, 286 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
309 scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner, 287 scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
310 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner, 288 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner,
311 AudioLogFactory* audio_log_factory) { 289 AudioLogFactory* audio_log_factory) {
312 DCHECK(task_runner); 290 DCHECK(task_runner);
313 DCHECK(worker_task_runner); 291 DCHECK(worker_task_runner);
314 ScopedAudioManagerPtr manager = CreateAudioManager( 292 std::unique_ptr<AudioManager> manager = CreateAudioManager(
315 std::move(task_runner), std::move(worker_task_runner), audio_log_factory); 293 std::move(task_runner), std::move(worker_task_runner), audio_log_factory);
316 #if BUILDFLAG(ENABLE_WEBRTC) 294 #if BUILDFLAG(ENABLE_WEBRTC)
317 manager->InitializeOutputDebugRecording(std::move(file_task_runner)); 295 manager->InitializeOutputDebugRecording(std::move(file_task_runner));
318 #endif 296 #endif
319 return manager; 297 return manager;
320 } 298 }
321 299
322 // static 300 // static
323 ScopedAudioManagerPtr AudioManager::CreateForTesting( 301 std::unique_ptr<AudioManager> AudioManager::CreateForTesting(
324 scoped_refptr<base::SingleThreadTaskRunner> task_runner) { 302 scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
325 #if defined(OS_WIN) 303 #if defined(OS_WIN)
326 GetHelper()->InitializeCOMForTesting(); 304 GetHelper()->InitializeCOMForTesting();
327 #endif 305 #endif
328 return Create(task_runner, task_runner, task_runner, 306 return Create(task_runner, task_runner, task_runner,
329 GetHelper()->fake_log_factory()); 307 GetHelper()->fake_log_factory());
330 } 308 }
331 309
332 // static 310 // static
333 void AudioManager::StartHangMonitorIfNeeded( 311 void AudioManager::StartHangMonitorIfNeeded(
(...skipping 19 matching lines...) Expand all
353 return GetHelper()->app_name(); 331 return GetHelper()->app_name();
354 } 332 }
355 #endif 333 #endif
356 334
357 // static 335 // static
358 AudioManager* AudioManager::Get() { 336 AudioManager* AudioManager::Get() {
359 return g_last_created; 337 return g_last_created;
360 } 338 }
361 339
362 } // namespace media 340 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698