Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(863)

Side by Side Diff: base/timer/timer.cc

Issue 2912433002: Fix race in base::Timer when SetTaskRunner() is used
Patch Set: rebase Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/timer/timer.h ('k') | build/sanitizers/tsan_suppressions.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/timer/timer.h" 5 #include "base/timer/timer.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <utility> 9 #include <utility>
10 10
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 DCHECK(origin_sequence_checker_.CalledOnValidSequence()); 132 DCHECK(origin_sequence_checker_.CalledOnValidSequence());
133 133
134 posted_from_ = posted_from; 134 posted_from_ = posted_from;
135 delay_ = delay; 135 delay_ = delay;
136 user_task_ = user_task; 136 user_task_ = user_task;
137 137
138 Reset(); 138 Reset();
139 } 139 }
140 140
141 void Timer::Stop() { 141 void Timer::Stop() {
142 // TODO(gab): Enable this when it's no longer called racily from 142 DCHECK(origin_sequence_checker_.CalledOnValidSequence());
143 // RunScheduledTask(): https://crbug.com/587199.
144 // DCHECK(origin_sequence_checker_.CalledOnValidSequence());
145 143
146 is_running_ = false; 144 is_running_ = false;
147 if (!retain_user_task_) 145 if (!retain_user_task_)
148 user_task_.Reset(); 146 user_task_.Reset();
149 // No more member accesses here: |this| could be deleted after freeing 147 // No more member accesses here: |this| could be deleted after freeing
150 // |user_task_|. 148 // |user_task_|.
151 } 149 }
152 150
153 void Timer::Reset() { 151 void Timer::Reset() {
154 DCHECK(origin_sequence_checker_.CalledOnValidSequence()); 152 DCHECK(origin_sequence_checker_.CalledOnValidSequence());
(...skipping 17 matching lines...) Expand all
172 is_running_ = true; 170 is_running_ = true;
173 return; 171 return;
174 } 172 }
175 173
176 // We can't reuse the |scheduled_task_|, so abandon it and post a new one. 174 // We can't reuse the |scheduled_task_|, so abandon it and post a new one.
177 AbandonScheduledTask(); 175 AbandonScheduledTask();
178 PostNewScheduledTask(delay_); 176 PostNewScheduledTask(delay_);
179 } 177 }
180 178
181 TimeTicks Timer::Now() const { 179 TimeTicks Timer::Now() const {
182 // TODO(gab): Enable this when it's no longer called racily from 180 DCHECK(origin_sequence_checker_.CalledOnValidSequence());
183 // RunScheduledTask(): https://crbug.com/587199.
184 // DCHECK(origin_sequence_checker_.CalledOnValidSequence());
185 return tick_clock_ ? tick_clock_->NowTicks() : TimeTicks::Now(); 181 return tick_clock_ ? tick_clock_->NowTicks() : TimeTicks::Now();
186 } 182 }
187 183
188 void Timer::PostNewScheduledTask(TimeDelta delay) { 184 void Timer::PostNewScheduledTask(TimeDelta delay) {
189 // TODO(gab): Enable this when it's no longer called racily from 185 DCHECK(origin_sequence_checker_.CalledOnValidSequence());
190 // RunScheduledTask(): https://crbug.com/587199.
191 // DCHECK(origin_sequence_checker_.CalledOnValidSequence());
192 DCHECK(!scheduled_task_); 186 DCHECK(!scheduled_task_);
193 is_running_ = true; 187 is_running_ = true;
194 scheduled_task_ = new BaseTimerTaskInternal(this); 188 scheduled_task_ = new BaseTimerTaskInternal(this);
195 if (delay > TimeDelta::FromMicroseconds(0)) { 189 if (delay > TimeDelta::FromMicroseconds(0)) {
196 // TODO(gab): Posting BaseTimerTaskInternal::Run to another sequence makes 190 SequencedTaskRunnerHandle::Get()->PostDelayedTask(
197 // this code racy. https://crbug.com/587199
198 GetTaskRunner()->PostDelayedTask(
199 posted_from_, 191 posted_from_,
200 base::BindOnce(&BaseTimerTaskInternal::Run, 192 base::BindOnce(&BaseTimerTaskInternal::Run,
201 base::Owned(scheduled_task_)), 193 base::Owned(scheduled_task_)),
202 delay); 194 delay);
203 scheduled_run_time_ = desired_run_time_ = Now() + delay; 195 scheduled_run_time_ = desired_run_time_ = Now() + delay;
204 } else { 196 } else {
205 GetTaskRunner()->PostTask(posted_from_, 197 SequencedTaskRunnerHandle::Get()->PostTask(
206 base::BindOnce(&BaseTimerTaskInternal::Run, 198 posted_from_, base::BindOnce(&BaseTimerTaskInternal::Run,
207 base::Owned(scheduled_task_))); 199 base::Owned(scheduled_task_)));
208 scheduled_run_time_ = desired_run_time_ = TimeTicks(); 200 scheduled_run_time_ = desired_run_time_ = TimeTicks();
209 } 201 }
210 } 202 }
211 203
212 scoped_refptr<SequencedTaskRunner> Timer::GetTaskRunner() {
213 return task_runner_.get() ? task_runner_ : SequencedTaskRunnerHandle::Get();
214 }
215
216 void Timer::AbandonScheduledTask() { 204 void Timer::AbandonScheduledTask() {
217 // TODO(gab): Enable this when it's no longer called racily from 205 DCHECK(origin_sequence_checker_.CalledOnValidSequence());
218 // RunScheduledTask() -> Stop(): https://crbug.com/587199.
219 // DCHECK(origin_sequence_checker_.CalledOnValidSequence());
220 if (scheduled_task_) { 206 if (scheduled_task_) {
221 scheduled_task_->Abandon(); 207 scheduled_task_->Abandon();
222 scheduled_task_ = nullptr; 208 scheduled_task_ = nullptr;
223 } 209 }
224 } 210 }
225 211
226 void Timer::RunScheduledTask() { 212 void Timer::RunScheduledTask() {
227 // TODO(gab): Enable this when it's no longer called racily: 213 DCHECK(origin_sequence_checker_.CalledOnValidSequence());
228 // https://crbug.com/587199.
229 // DCHECK(origin_sequence_checker_.CalledOnValidSequence());
230 214
231 // Task may have been disabled. 215 // Task may have been disabled.
232 if (!is_running_) 216 if (!is_running_)
233 return; 217 return;
234 218
235 // First check if we need to delay the task because of a new target time. 219 // First check if we need to delay the task because of a new target time.
236 if (desired_run_time_ > scheduled_run_time_) { 220 if (desired_run_time_ > scheduled_run_time_) {
237 // Now() can be expensive, so only call it if we know the user has changed 221 // Now() can be expensive, so only call it if we know the user has changed
238 // the |desired_run_time_|. 222 // the |desired_run_time_|.
239 TimeTicks now = Now(); 223 TimeTicks now = Now();
240 // Task runner may have called us late anyway, so only post a continuation 224 // Task runner may have called us late anyway, so only post a continuation
241 // task if the |desired_run_time_| is in the future. 225 // task if the |desired_run_time_| is in the future.
242 if (desired_run_time_ > now) { 226 if (desired_run_time_ > now) {
243 // Post a new task to span the remaining time. 227 // Post a new task to span the remaining time.
244 PostNewScheduledTask(desired_run_time_ - now); 228 PostNewScheduledTask(desired_run_time_ - now);
245 return; 229 return;
246 } 230 }
247 } 231 }
248 232
249 // Make a local copy of the task to run. The Stop method will reset the 233 // Make a local copy of the task to run. The Stop method will reset the
250 // |user_task_| member if |retain_user_task_| is false. 234 // |user_task_| member if |retain_user_task_| is false.
251 base::Closure task = user_task_; 235 base::Closure task = user_task_;
252 236
253 if (is_repeating_) 237 if (is_repeating_)
254 PostNewScheduledTask(delay_); 238 PostNewScheduledTask(delay_);
255 else 239 else
256 Stop(); 240 Stop();
257 241
258 task.Run(); 242 if (task_runner_ && !task_runner_->RunsTasksOnCurrentThread())
243 task_runner_->PostTask(posted_from_, std::move(task));
244 else
245 task.Run();
259 246
260 // No more member accesses here: |this| could be deleted at this point. 247 // No more member accesses here: |this| could be deleted at this point.
261 } 248 }
262 249
263 } // namespace base 250 } // namespace base
OLDNEW
« no previous file with comments | « base/timer/timer.h ('k') | build/sanitizers/tsan_suppressions.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698