Commit 35f88255 authored by Alex Clarke's avatar Alex Clarke Committed by Commit Bot

ThreadControllerWithMessagePumpImpl cap delays at one day

It's important to cap delays at one day or bad things can happen
on certain platforms.

Also removes a redundant call to ScheduleDelayedWork.

Bug: 863341, 850450
Change-Id: Idfb95a5e5d800255caff74d0718db600b9348335
Reviewed-on: https://chromium-review.googlesource.com/c/1314489Reviewed-by: default avatarAlexander Timin <altimin@chromium.org>
Commit-Queue: Alex Clarke <alexclarke@chromium.org>
Cr-Commit-Position: refs/heads/master@{#604980}
parent 4ae6290e
...@@ -12,6 +12,19 @@ ...@@ -12,6 +12,19 @@
namespace base { namespace base {
namespace sequence_manager { namespace sequence_manager {
namespace internal { namespace internal {
namespace {
// Returns |next_run_time| capped at 1 day from |lazy_now|. This is used to
// mitigate https://crbug.com/850450 where some platforms are unhappy with
// delays > 100,000,000 seconds. In practice, a diagnosis metric showed that no
// sleep > 1 hour ever completes (always interrupted by an earlier MessageLoop
// event) and 99% of completed sleeps are the ones scheduled for <= 1 second.
// Details @ https://crrev.com/c/1142589.
TimeTicks CapAtOneDay(TimeTicks next_run_time, LazyNow* lazy_now) {
return std::min(next_run_time, lazy_now->Now() + TimeDelta::FromDays(1));
}
} // namespace
ThreadControllerWithMessagePumpImpl::ThreadControllerWithMessagePumpImpl( ThreadControllerWithMessagePumpImpl::ThreadControllerWithMessagePumpImpl(
std::unique_ptr<MessagePump> message_pump, std::unique_ptr<MessagePump> message_pump,
...@@ -94,6 +107,8 @@ void ThreadControllerWithMessagePumpImpl::SetNextDelayedDoWork( ...@@ -94,6 +107,8 @@ void ThreadControllerWithMessagePumpImpl::SetNextDelayedDoWork(
if (main_thread_only().immediate_do_work_posted || InTopLevelDoWork()) if (main_thread_only().immediate_do_work_posted || InTopLevelDoWork())
return; return;
run_time = CapAtOneDay(run_time, lazy_now);
main_thread_only().next_delayed_do_work = run_time; main_thread_only().next_delayed_do_work = run_time;
pump_->ScheduleDelayedWork(run_time); pump_->ScheduleDelayedWork(run_time);
} }
...@@ -195,7 +210,7 @@ bool ThreadControllerWithMessagePumpImpl::DoWorkImpl( ...@@ -195,7 +210,7 @@ bool ThreadControllerWithMessagePumpImpl::DoWorkImpl(
main_thread_only().immediate_do_work_posted = true; main_thread_only().immediate_do_work_posted = true;
return true; return true;
} else if (do_work_delay != TimeDelta::Max()) { } else if (do_work_delay != TimeDelta::Max()) {
*next_run_time = lazy_now.Now() + do_work_delay; *next_run_time = CapAtOneDay(lazy_now.Now() + do_work_delay, &lazy_now);
// Cancels any previously scheduled delayed wake-ups. // Cancels any previously scheduled delayed wake-ups.
pump_->ScheduleDelayedWork(*next_run_time); pump_->ScheduleDelayedWork(*next_run_time);
} else { } else {
......
...@@ -84,6 +84,10 @@ TimeTicks Seconds(int seconds) { ...@@ -84,6 +84,10 @@ TimeTicks Seconds(int seconds) {
return TimeTicks() + TimeDelta::FromSeconds(seconds); return TimeTicks() + TimeDelta::FromSeconds(seconds);
} }
TimeTicks Days(int seconds) {
return TimeTicks() + TimeDelta::FromDays(seconds);
}
} // namespace } // namespace
TEST(ThreadControllerWithMessagePumpTest, ScheduleDelayedWork) { TEST(ThreadControllerWithMessagePumpTest, ScheduleDelayedWork) {
...@@ -99,7 +103,7 @@ TEST(ThreadControllerWithMessagePumpTest, ScheduleDelayedWork) { ...@@ -99,7 +103,7 @@ TEST(ThreadControllerWithMessagePumpTest, ScheduleDelayedWork) {
FakeSequencedTaskSource task_source(&clock); FakeSequencedTaskSource task_source(&clock);
thread_controller.SetSequencedTaskSource(&task_source); thread_controller.SetSequencedTaskSource(&task_source);
base::TimeTicks next_run_time; TimeTicks next_run_time;
MockCallback<OnceClosure> task1; MockCallback<OnceClosure> task1;
task_source.AddTask(PendingTask(FROM_HERE, task1.Get(), Seconds(10))); task_source.AddTask(PendingTask(FROM_HERE, task1.Get(), Seconds(10)));
...@@ -125,7 +129,7 @@ TEST(ThreadControllerWithMessagePumpTest, ScheduleDelayedWork) { ...@@ -125,7 +129,7 @@ TEST(ThreadControllerWithMessagePumpTest, ScheduleDelayedWork) {
testing::Mock::VerifyAndClearExpectations(message_pump); testing::Mock::VerifyAndClearExpectations(message_pump);
testing::Mock::VerifyAndClearExpectations(&task1); testing::Mock::VerifyAndClearExpectations(&task1);
// Call DoWork immeidately after the previous call. Expect a new task // Call DoWork immediately after the previous call. Expect a new task
// to be run. // to be run.
EXPECT_CALL(task2, Run()).Times(1); EXPECT_CALL(task2, Run()).Times(1);
EXPECT_CALL(*message_pump, ScheduleDelayedWork(Seconds(20))); EXPECT_CALL(*message_pump, ScheduleDelayedWork(Seconds(20)));
...@@ -144,5 +148,55 @@ TEST(ThreadControllerWithMessagePumpTest, ScheduleDelayedWork) { ...@@ -144,5 +148,55 @@ TEST(ThreadControllerWithMessagePumpTest, ScheduleDelayedWork) {
testing::Mock::VerifyAndClearExpectations(&task3); testing::Mock::VerifyAndClearExpectations(&task3);
} }
TEST(ThreadControllerWithMessagePumpTest, SetNextDelayedDoWork) {
MockMessagePump* message_pump;
std::unique_ptr<MockMessagePump> pump =
std::make_unique<testing::StrictMock<MockMessagePump>>();
message_pump = pump.get();
SimpleTestTickClock clock;
ThreadControllerForTest thread_controller(std::move(pump), &clock);
EXPECT_CALL(*message_pump, ScheduleDelayedWork(Seconds(123)));
LazyNow lazy_now(&clock);
thread_controller.SetNextDelayedDoWork(&lazy_now, Seconds(123));
}
TEST(ThreadControllerWithMessagePumpTest, SetNextDelayedDoWork_CapAtOneDay) {
MockMessagePump* message_pump;
std::unique_ptr<MockMessagePump> pump =
std::make_unique<testing::StrictMock<MockMessagePump>>();
message_pump = pump.get();
SimpleTestTickClock clock;
ThreadControllerForTest thread_controller(std::move(pump), &clock);
EXPECT_CALL(*message_pump, ScheduleDelayedWork(Days(1)));
LazyNow lazy_now(&clock);
thread_controller.SetNextDelayedDoWork(&lazy_now, Days(2));
}
TEST(ThreadControllerWithMessagePumpTest, DelayedWork_CapAtOneDay) {
MockMessagePump* message_pump;
std::unique_ptr<MockMessagePump> pump =
std::make_unique<testing::StrictMock<MockMessagePump>>();
message_pump = pump.get();
SimpleTestTickClock clock;
ThreadControllerForTest thread_controller(std::move(pump), &clock);
thread_controller.SetWorkBatchSize(1);
FakeSequencedTaskSource task_source(&clock);
thread_controller.SetSequencedTaskSource(&task_source);
MockCallback<OnceClosure> task1;
task_source.AddTask(PendingTask(FROM_HERE, task1.Get(), Days(10)));
EXPECT_CALL(*message_pump, ScheduleDelayedWork(Days(1)));
EXPECT_FALSE(thread_controller.DoWork());
}
} // namespace sequence_manager } // namespace sequence_manager
} // namespace base } // namespace base
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