Commit 22149529 authored by jlevasseur's avatar jlevasseur Committed by Commit bot

ThreadWatcher: fix use-after-delete bug.

When a StartupTimeBomb instance deletes itself, it may schedule a future
task to complete the deletion, and this future task must not reference
the destructed instance.

BUG=none
TEST=unit tests

Review-Url: https://codereview.chromium.org/2296793003
Cr-Commit-Position: refs/heads/master@{#415716}
parent 7dc48990
......@@ -886,25 +886,30 @@ void StartupTimeBomb::Arm(const base::TimeDelta& duration) {
void StartupTimeBomb::Disarm() {
DCHECK_EQ(thread_id_, base::PlatformThread::CurrentId());
if (startup_watchdog_) {
startup_watchdog_->Disarm();
startup_watchdog_->Cleanup();
DeleteStartupWatchdog();
base::Watchdog* startup_watchdog = startup_watchdog_;
startup_watchdog_ = nullptr;
startup_watchdog->Disarm();
startup_watchdog->Cleanup();
DeleteStartupWatchdog(thread_id_, startup_watchdog);
}
}
void StartupTimeBomb::DeleteStartupWatchdog() {
DCHECK_EQ(thread_id_, base::PlatformThread::CurrentId());
if (startup_watchdog_->IsJoinable()) {
// static
void StartupTimeBomb::DeleteStartupWatchdog(
const base::PlatformThreadId thread_id,
base::Watchdog* startup_watchdog) {
DCHECK_EQ(thread_id, base::PlatformThread::CurrentId());
if (startup_watchdog->IsJoinable()) {
// Allow the watchdog thread to shutdown on UI. Watchdog thread shutdowns
// very fast.
base::ThreadRestrictions::ScopedAllowIO allow_io;
delete startup_watchdog_;
startup_watchdog_ = nullptr;
delete startup_watchdog;
return;
}
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, base::Bind(&StartupTimeBomb::DeleteStartupWatchdog,
base::Unretained(this)),
FROM_HERE, base::Bind(&StartupTimeBomb::DeleteStartupWatchdog, thread_id,
base::Unretained(startup_watchdog)),
base::TimeDelta::FromSeconds(10));
}
......
......@@ -626,9 +626,10 @@ class StartupTimeBomb {
static void DisarmStartupTimeBomb();
private:
// Deletes |startup_watchdog_| if it is joinable. If |startup_watchdog_| is
// not joinable, then it will post a delayed task to try again.
void DeleteStartupWatchdog();
// Deletes the watchdog thread if it is joinable; otherwise it posts a delayed
// task to try again.
static void DeleteStartupWatchdog(const base::PlatformThreadId thread_id,
base::Watchdog* startup_watchdog);
// The singleton of this class.
static StartupTimeBomb* g_startup_timebomb_;
......
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