Index: media/audio/audio_manager.cc |
diff --git a/media/audio/audio_manager.cc b/media/audio/audio_manager.cc |
index 6d5d70d087c204d29df1714536b18e032ccd2374..cad09a599cd76e0074bcbc529c1c99893dba252b 100644 |
--- a/media/audio/audio_manager.cc |
+++ b/media/audio/audio_manager.cc |
@@ -14,7 +14,58 @@ |
namespace media { |
namespace { |
AudioManager* g_last_created = NULL; |
-static base::LazyInstance<FakeAudioLogFactory>::Leaky g_fake_log_factory = |
+ |
+// Helper class for managing global AudioManager data and hang timers. If the |
+// audio thread is unresponsive for more than a minute we want to crash the |
+// process so we can catch offenders quickly in the field. |
+class AudioManagerHelper { |
+ public: |
+ AudioManagerHelper() : max_hung_task_time_(base::TimeDelta::FromMinutes(1)) {} |
+ ~AudioManagerHelper() {} |
+ |
+ void StartHangTimer( |
+ const scoped_refptr<base::SingleThreadTaskRunner>& monitor_task_runner) { |
+ CHECK(!monitor_task_runner_); |
nasko
2015/03/25 17:28:00
nit: Can we also check that this is called on the
DaleCurtis
2015/03/25 20:28:56
Sent you a chat about this, because I'm not clear
nasko
2015/03/25 20:52:23
Clarified over chat. Since this method isn't expec
|
+ monitor_task_runner_ = monitor_task_runner; |
+ UpdateLastAudioThreadTimeTick(); |
+ CrashOnAudioThreadHang(); |
+ } |
+ |
+ void CrashOnAudioThreadHang() { |
+ base::AutoLock lock(hang_lock_); |
+ CHECK(base::TimeTicks::Now() - last_audio_thread_timer_tick_ <= |
+ max_hung_task_time_); |
+ monitor_task_runner_->PostDelayedTask( |
+ FROM_HERE, base::Bind(&AudioManagerHelper::CrashOnAudioThreadHang, |
+ base::Unretained(this)), |
nasko
2015/03/25 17:28:00
Are we guaranteed that this object will never be n
DaleCurtis
2015/03/25 20:28:56
Yes, it's a LazyInstance::Leaky, which means it'll
nasko
2015/03/25 20:52:23
Acknowledged.
|
+ max_hung_task_time_); |
+ } |
+ |
+ void UpdateLastAudioThreadTimeTick() { |
+ base::AutoLock lock(hang_lock_); |
+ last_audio_thread_timer_tick_ = base::TimeTicks::Now(); |
+ g_last_created->GetTaskRunner()->PostDelayedTask( |
+ FROM_HERE, |
+ base::Bind(&AudioManagerHelper::UpdateLastAudioThreadTimeTick, |
+ base::Unretained(this)), |
+ max_hung_task_time_ / 2); |
+ } |
+ |
+ AudioLogFactory* fake_log_factory() { return &fake_log_factory_; } |
+ |
+ private: |
+ FakeAudioLogFactory fake_log_factory_; |
+ |
+ const base::TimeDelta max_hung_task_time_; |
+ scoped_refptr<base::SingleThreadTaskRunner> monitor_task_runner_; |
+ |
+ base::Lock hang_lock_; |
+ base::TimeTicks last_audio_thread_timer_tick_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(AudioManagerHelper); |
+}; |
+ |
+static base::LazyInstance<AudioManagerHelper>::Leaky g_helper = |
LAZY_INSTANCE_INITIALIZER; |
} |
@@ -36,8 +87,17 @@ AudioManager* AudioManager::Create(AudioLogFactory* audio_log_factory) { |
} |
// static |
+AudioManager* AudioManager::CreateWithHangTimer( |
+ AudioLogFactory* audio_log_factory, |
+ const scoped_refptr<base::SingleThreadTaskRunner>& monitor_task_runner) { |
+ AudioManager* manager = Create(audio_log_factory); |
+ g_helper.Pointer()->StartHangTimer(monitor_task_runner); |
+ return manager; |
+} |
+ |
+// static |
AudioManager* AudioManager::CreateForTesting() { |
- return Create(g_fake_log_factory.Pointer()); |
+ return Create(g_helper.Pointer()->fake_log_factory()); |
} |
// static |