| Index: content/child/scheduler/task_queue_manager.cc
|
| diff --git a/content/child/scheduler/task_queue_manager.cc b/content/child/scheduler/task_queue_manager.cc
|
| index 386ebd0c955cc642f6ea09c8db56d004d33e9a41..f3bd5b96ebb70a83e3f92c83d742ed6490764857 100644
|
| --- a/content/child/scheduler/task_queue_manager.cc
|
| +++ b/content/child/scheduler/task_queue_manager.cc
|
| @@ -464,6 +464,7 @@ TaskQueueManager::TaskQueueManager(
|
| time_source_(nullptr),
|
| disabled_by_default_tracing_category_(
|
| disabled_by_default_tracing_category),
|
| + deletion_sentinel_(new DeletionSentinel()),
|
| weak_factory_(this) {
|
| DCHECK(main_task_runner->RunsTasksOnCurrentThread());
|
| TRACE_EVENT_OBJECT_CREATED_WITH_ID(disabled_by_default_tracing_category,
|
| @@ -596,7 +597,9 @@ void TaskQueueManager::DoWork(bool posted_from_main_thread) {
|
| // Note that this function won't post another call to DoWork if one is
|
| // already pending, so it is safe to call it in a loop.
|
| MaybePostDoWorkOnMainRunner();
|
| - ProcessTaskFromWorkQueue(queue_index, i > 0, &previous_task);
|
| +
|
| + if (ProcessTaskFromWorkQueue(queue_index, i > 0, &previous_task))
|
| + return; // The TaskQueueManager got deleted, we must bail out.
|
|
|
| if (!UpdateWorkQueues(&previous_task))
|
| return;
|
| @@ -616,11 +619,12 @@ void TaskQueueManager::DidQueueTask(base::PendingTask* pending_task) {
|
| task_annotator_.DidQueueTask("TaskQueueManager::PostTask", *pending_task);
|
| }
|
|
|
| -void TaskQueueManager::ProcessTaskFromWorkQueue(
|
| +bool TaskQueueManager::ProcessTaskFromWorkQueue(
|
| size_t queue_index,
|
| bool has_previous_task,
|
| base::PendingTask* previous_task) {
|
| DCHECK(main_thread_checker_.CalledOnValidThread());
|
| + scoped_refptr<DeletionSentinel> protect(deletion_sentinel_);
|
| internal::TaskQueue* queue = Queue(queue_index);
|
| base::PendingTask pending_task = queue->TakeTaskFromWorkQueue();
|
| if (!pending_task.nestable && main_task_runner_->IsNested()) {
|
| @@ -640,9 +644,16 @@ void TaskQueueManager::ProcessTaskFromWorkQueue(
|
| }
|
| task_annotator_.RunTask("TaskQueueManager::PostTask",
|
| "TaskQueueManager::RunTask", pending_task);
|
| +
|
| + // Detect if the TaskQueueManager just got deleted. If this happens we must
|
| + // not access any member variables after this point.
|
| + if (protect->HasOneRef())
|
| + return true;
|
| +
|
| pending_task.task.Reset();
|
| *previous_task = pending_task;
|
| }
|
| + return false;
|
| }
|
|
|
| bool TaskQueueManager::RunsTasksOnCurrentThread() const {
|
|
|