summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorshess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-11 23:38:38 +0000
committershess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-11 23:38:38 +0000
commitcf1ccbc721d809bbeaf87ded9c4df4b160bb4ffd (patch)
treef49c0803105cef9c8ae4f9bdb4762da0731a48c9
parent8150b76b7b9007f54b7878e62c4aa823ee31a45b (diff)
downloadchromium_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.cc37
-rw-r--r--content/renderer/pepper/pepper_hung_plugin_filter.h5
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();