Commit 7e1b5a3c authored by derat's avatar derat Committed by Commit bot

chromeos: Fix renderer-freezing race during aborted suspend.

Fix a (long-standing?) race where
chromeos::PowerManagerClient could notify RendererFreezer
that a suspend attempt was imminent *after* already telling
it that the attempt was done.

Also make PowerManagerClient not notify powerd about regular
or dark suspend readiness after it's already seen a
SuspendDone signal.

Add a bunch of unit tests exercising this code, too, and
rework the comments on some previously-added tests.

BUG=646912

Review-Url: https://codereview.chromium.org/2340153002
Cr-Commit-Position: refs/heads/master@{#418887}
parent e0dd83fd
......@@ -543,6 +543,7 @@ class PowerManagerClientImpl : public PowerManagerClient {
suspend_is_pending_ = true;
suspending_from_dark_resume_ = in_dark_resume;
num_pending_suspend_readiness_callbacks_ = 0;
if (suspending_from_dark_resume_)
FOR_EACH_OBSERVER(Observer, observers_, DarkSuspendImminent());
else
......@@ -567,9 +568,23 @@ class PowerManagerClientImpl : public PowerManagerClient {
<< " suspend_id=" << proto.suspend_id()
<< " duration=" << duration.InSeconds() << " sec";
if (render_process_manager_delegate_)
// RenderProcessManagerDelegate is only notified that suspend is imminent
// when readiness is being reported to powerd. If the suspend attempt was
// cancelled before then, we shouldn't notify the delegate about completion.
const bool cancelled_while_regular_suspend_pending =
suspend_is_pending_ && !suspending_from_dark_resume_;
if (render_process_manager_delegate_ &&
!cancelled_while_regular_suspend_pending)
render_process_manager_delegate_->SuspendDone();
// powerd always pairs each SuspendImminent signal with SuspendDone before
// starting the next suspend attempt, so we should no longer report
// readiness for any in-progress suspend attempts.
pending_suspend_id_ = -1;
suspend_is_pending_ = false;
suspending_from_dark_resume_ = false;
num_pending_suspend_readiness_callbacks_ = 0;
FOR_EACH_OBSERVER(
PowerManagerClient::Observer, observers_, SuspendDone(duration));
base::PowerMonitorDeviceSource::HandleSystemResumed();
......@@ -711,7 +726,9 @@ class PowerManagerClientImpl : public PowerManagerClient {
// Reports suspend readiness to powerd if no observers are still holding
// suspend readiness callbacks.
void MaybeReportSuspendReadiness() {
if (!suspend_is_pending_ || num_pending_suspend_readiness_callbacks_ > 0)
CHECK(suspend_is_pending_);
if (num_pending_suspend_readiness_callbacks_ > 0)
return;
std::string method_name;
......@@ -756,16 +773,16 @@ class PowerManagerClientImpl : public PowerManagerClient {
dbus::ObjectProxy* power_manager_proxy_;
base::ObserverList<Observer> observers_;
// The delay_id_ obtained from the RegisterSuspendDelay request.
// The delay ID obtained from the RegisterSuspendDelay request.
int32_t suspend_delay_id_;
bool has_suspend_delay_id_;
// The delay_id_ obtained from the RegisterDarkSuspendDelay request.
// The delay ID obtained from the RegisterDarkSuspendDelay request.
int32_t dark_suspend_delay_id_;
bool has_dark_suspend_delay_id_;
// powerd-supplied ID corresponding to an imminent suspend attempt that is
// currently being delayed.
// powerd-supplied ID corresponding to an imminent (either regular or dark)
// suspend attempt that is currently being delayed.
int32_t pending_suspend_id_;
bool suspend_is_pending_;
......
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