diff options
author | shess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-11 23:38:38 +0000 |
---|---|---|
committer | shess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-11 23:38:38 +0000 |
commit | cf1ccbc721d809bbeaf87ded9c4df4b160bb4ffd (patch) | |
tree | f49c0803105cef9c8ae4f9bdb4762da0731a48c9 | |
parent | 8150b76b7b9007f54b7878e62c4aa823ee31a45b (diff) | |
download | chromium_src-cf1ccbc721d809bbeaf87ded9c4df4b160bb4ffd.zip chromium_src-cf1ccbc721d809bbeaf87ded9c4df4b160bb4ffd.tar.gz chromium_src-cf1ccbc721d809bbeaf87ded9c4df4b160bb4ffd.tar.bz2 |
Merge 155858 - Prevent a 0-time delay in the hung plugin checker.
[Note, will also merge r156044 which fixes a bug in this.]
Fix a bug in the Pepper hung plugin checker where it would post a task to check for hangs with a negative timeout, causing an assertion.
This would result in the immediate running of the task and would cause a loop of checking in the renderer process that would use all the CPU. This condition is hit when we're blocked for longer than the hang threshold, but due to another message coming in from the plugin, haven't yet hit the "hard" hang threshold.
This also adds a fatal assertion for this condition if this patch doesn't fix it, since we want the reports rather than get weird hangs.
BUG=144077
Review URL: https://chromiumcodereview.appspot.com/10914183
TBR=brettw@chromium.org
Review URL: https://chromiumcodereview.appspot.com/10910213
git-svn-id: svn://svn.chromium.org/chrome/branches/1229/src@156175 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | content/renderer/pepper/pepper_hung_plugin_filter.cc | 37 | ||||
-rw-r--r-- | content/renderer/pepper/pepper_hung_plugin_filter.h | 5 |
2 files changed, 33 insertions, 9 deletions
diff --git a/content/renderer/pepper/pepper_hung_plugin_filter.cc b/content/renderer/pepper/pepper_hung_plugin_filter.cc index 71ff412..60853f7 100644 --- a/content/renderer/pepper/pepper_hung_plugin_filter.cc +++ b/content/renderer/pepper/pepper_hung_plugin_filter.cc @@ -88,21 +88,19 @@ void PepperHungPluginFilter::EnsureTimerScheduled() { } void PepperHungPluginFilter::MayHaveBecomeUnhung() { - if (!hung_plugin_showing_ || IsHung()) + if (!hung_plugin_showing_ || IsHung(base::TimeTicks::Now())) return; SendHungMessage(false); hung_plugin_showing_ = false; } -bool PepperHungPluginFilter::IsHung() const { +bool PepperHungPluginFilter::IsHung(base::TimeTicks now) const { lock_.AssertAcquired(); if (!pending_sync_message_count_) return false; // Not blocked on a sync message. - base::TimeTicks now = base::TimeTicks::Now(); - DCHECK(!began_blocking_time_.is_null()); if (now - began_blocking_time_ >= base::TimeDelta::FromSeconds(kBlockedHardThresholdSec)) @@ -123,16 +121,41 @@ void PepperHungPluginFilter::OnHangTimer() { base::AutoLock lock(lock_); timer_task_pending_ = false; - if (!IsHung()) { + // Save this up front so all deltas computed below will agree on "now." + base::TimeTicks now = base::TimeTicks::Now(); + + if (!IsHung(now)) { if (pending_sync_message_count_ > 0) { // Got a timer message while we're waiting on a sync message. We need // to schedule another timer message because the latest sync message // would not have scheduled one (we only have one out-standing timer at // a time). DCHECK(!began_blocking_time_.is_null()); + base::TimeDelta time_blocked = now - began_blocking_time_; + + // This is the delay we're considered hung since we first started + // blocking. base::TimeDelta delay = - base::TimeDelta::FromSeconds(kHungThresholdSec) - - (base::TimeTicks::Now() - began_blocking_time_); + base::TimeDelta::FromSeconds(kHungThresholdSec) - time_blocked; + + // If another message was received from the plugin since we first started + // blocking, but we haven't hit the "hard" threshold yet, we won't be + // considered hung even though we're beyond the "regular" hung threshold. + // In this case, schedule a timer at the hard threshold. + if (delay <= base::TimeDelta()) { + delay = base::TimeDelta::FromSeconds(kBlockedHardThresholdSec) - + time_blocked; + } + + // If the delay is negative or zero, another timer task will be + // immediately posted, and if the condition persists we could end up + // spinning on hang timers and not getting any work done, causing our + // own "kind of" hang (although the message loop is running little work + // will be getting done) in the renderer! If the timings or logic are + // off, we'd prefer to get a crash dump and know about it. + CHECK(delay <= base::TimeDelta()); + + timer_task_pending_ = false; io_loop_->PostDelayedTask(FROM_HERE, base::Bind(&PepperHungPluginFilter::OnHangTimer, this), delay); diff --git a/content/renderer/pepper/pepper_hung_plugin_filter.h b/content/renderer/pepper/pepper_hung_plugin_filter.h index 2d2dc53..08dcbf4 100644 --- a/content/renderer/pepper/pepper_hung_plugin_filter.h +++ b/content/renderer/pepper/pepper_hung_plugin_filter.h @@ -60,8 +60,9 @@ class PepperHungPluginFilter void MayHaveBecomeUnhung(); // Checks if the plugin is considered hung based on whether it has been - // blocked for long enough. - bool IsHung() const; + // blocked for long enough. The current time is passed in so that the deltas + // can be synchronized with the caller's computations. + bool IsHung(base::TimeTicks now) const; // Timer handler that checks for a hang after a timeout. void OnHangTimer(); |