Commit 615510b0 authored by dalecurtis's avatar dalecurtis Committed by Commit bot

Update last audio tick time during suspend and resume.

If someone suspends their computer and resumes more than a minute
later, the browser io thread may tick before the audio thread can
update the last tick time ==> crash :(

The solution is to disable hang detection during suspend and only
reenable it once resume completes; at which point we can update
the tick count. If we're actually hung, we'll crash after the next
interval elapses.

BUG=471046
TEST=none

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

Cr-Commit-Position: refs/heads/master@{#322509}
parent 3c7961f3
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "base/lazy_instance.h" #include "base/lazy_instance.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
#include "base/power_monitor/power_monitor.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "media/audio/fake_audio_log_factory.h" #include "media/audio/fake_audio_log_factory.h"
...@@ -19,24 +20,46 @@ AudioManager* g_last_created = NULL; ...@@ -19,24 +20,46 @@ AudioManager* g_last_created = NULL;
// Helper class for managing global AudioManager data and hang timers. If the // 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 // audio thread is unresponsive for more than a minute we want to crash the
// process so we can catch offenders quickly in the field. // process so we can catch offenders quickly in the field.
class AudioManagerHelper { class AudioManagerHelper : public base::PowerObserver {
public: public:
AudioManagerHelper() : max_hung_task_time_(base::TimeDelta::FromMinutes(1)) {} AudioManagerHelper()
~AudioManagerHelper() {} : max_hung_task_time_(base::TimeDelta::FromMinutes(1)),
hang_detection_enabled_(true) {}
~AudioManagerHelper() override {}
void StartHangTimer( void StartHangTimer(
const scoped_refptr<base::SingleThreadTaskRunner>& monitor_task_runner) { const scoped_refptr<base::SingleThreadTaskRunner>& monitor_task_runner) {
CHECK(!monitor_task_runner_); CHECK(!monitor_task_runner_);
monitor_task_runner_ = monitor_task_runner; monitor_task_runner_ = monitor_task_runner;
base::PowerMonitor::Get()->AddObserver(this);
UpdateLastAudioThreadTimeTick(); UpdateLastAudioThreadTimeTick();
CrashOnAudioThreadHang(); CrashOnAudioThreadHang();
} }
// Disable hang detection when the system goes into the suspend state.
void OnSuspend() override {
base::AutoLock lock(hang_lock_);
hang_detection_enabled_ = false;
}
// Reenable hang detection once the system comes out of the suspend state.
void OnResume() override {
base::AutoLock lock(hang_lock_);
hang_detection_enabled_ = true;
last_audio_thread_timer_tick_ = base::TimeTicks::Now();
}
// Runs on |monitor_task_runner| typically, but may be started on any thread. // Runs on |monitor_task_runner| typically, but may be started on any thread.
void CrashOnAudioThreadHang() { void CrashOnAudioThreadHang() {
base::AutoLock lock(hang_lock_); base::AutoLock lock(hang_lock_);
CHECK(base::TimeTicks::Now() - last_audio_thread_timer_tick_ <=
max_hung_task_time_); // Don't attempt to verify the tick time if the system is in the process of
// suspending or resuming.
if (hang_detection_enabled_) {
CHECK(base::TimeTicks::Now() - last_audio_thread_timer_tick_ <=
max_hung_task_time_);
}
monitor_task_runner_->PostDelayedTask( monitor_task_runner_->PostDelayedTask(
FROM_HERE, base::Bind(&AudioManagerHelper::CrashOnAudioThreadHang, FROM_HERE, base::Bind(&AudioManagerHelper::CrashOnAudioThreadHang,
base::Unretained(this)), base::Unretained(this)),
...@@ -63,6 +86,7 @@ class AudioManagerHelper { ...@@ -63,6 +86,7 @@ class AudioManagerHelper {
scoped_refptr<base::SingleThreadTaskRunner> monitor_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> monitor_task_runner_;
base::Lock hang_lock_; base::Lock hang_lock_;
bool hang_detection_enabled_;
base::TimeTicks last_audio_thread_timer_tick_; base::TimeTicks last_audio_thread_timer_tick_;
DISALLOW_COPY_AND_ASSIGN(AudioManagerHelper); DISALLOW_COPY_AND_ASSIGN(AudioManagerHelper);
......
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