Commit 8235b520 authored by ccameron@chromium.org's avatar ccameron@chromium.org

Fix crash in Mac ASAN RenderWidgetResizeHelper

It is possible for the TaskRunner to which the tasks were posted
to be destroyed before the RenderWidgetResizeHelper is destroyed.
Make sure that RenderWidgetResizeHelper is robust to this by having
tasks remove themselves from RenderWidgetResizeHelper's queue
when they are destroyed.

BUG=394775
TBR=sky@chromium.org

Review URL: https://codereview.chromium.org/399213003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@284224 0039d316-1c4b-4281-b951-d872f2087c98
parent 19014b41
......@@ -34,6 +34,9 @@ class RenderWidgetResizeHelper::EnqueuedTask {
int process_id_;
IPC::Message message_;
bool has_run_;
// Back-pointer to the ResizeHelper which has this task in its queue. Set
// to NULL when this task is removed from the queue.
RenderWidgetResizeHelper* helper_;
DISALLOW_COPY_AND_ASSIGN(EnqueuedTask);
......@@ -51,6 +54,12 @@ RenderWidgetResizeHelper::EnqueuedTask::EnqueuedTask(
}
RenderWidgetResizeHelper::EnqueuedTask::~EnqueuedTask() {
// Note that if the MessageLoop into which this task was posted is destroyed
// before the RenderWidgetResizeHelper, then the helper's list of tasks will
// point to freed data. Avoid this by removing tasks when they are freed, if
// they weren't already removed when they were run.
if (helper_)
helper_->RemoveEnqueuedTaskFromQueue(this);
}
void RenderWidgetResizeHelper::EnqueuedTask::Run() {
......@@ -58,7 +67,7 @@ void RenderWidgetResizeHelper::EnqueuedTask::Run() {
return;
if (helper_)
helper_->WillRunEnqueuedTask(this);
helper_->RemoveEnqueuedTaskFromQueue(this);
has_run_ = true;
switch (type_) {
......@@ -133,10 +142,11 @@ void RenderWidgetResizeHelper::PostEnqueuedTask(EnqueuedTask* task) {
base::Bind(&EnqueuedTask::Run, base::Owned(task)));
}
void RenderWidgetResizeHelper::WillRunEnqueuedTask(EnqueuedTask* task) {
void RenderWidgetResizeHelper::RemoveEnqueuedTaskFromQueue(EnqueuedTask* task) {
base::AutoLock lock(task_queue_lock_);
DCHECK(task_queue_.front() == task);
task_queue_.pop_front();
task->InvalidateHelper();
}
void RenderWidgetResizeHelper::PostRendererProcessMsg(
......
......@@ -82,12 +82,13 @@ class RenderWidgetResizeHelper {
void PostEnqueuedTask(EnqueuedTask* proxy);
// Called on the UI to remove the task from the queue when it is run.
void WillRunEnqueuedTask(EnqueuedTask* proxy);
void RemoveEnqueuedTaskFromQueue(EnqueuedTask* proxy);
// A queue of live messages. Must hold |task_queue_lock_| to access.
// The EnqueuedTask objects are removed from the front of the queue when
// they are run (either by TaskRunner they were posted to or by a call to
// WaitForSingleTaskToRun pulling them off of the queue).
// A queue of live messages. Must hold |task_queue_lock_| to access. Tasks
// are added only on the IO thread and removed only on the UI thread. The
// EnqueuedTask objects are removed from the front of the queue when they are
// run (by TaskRunner they were posted to, by a call to WaitForSingleTaskToRun
// pulling them off of the queue, or by TaskRunner when it is destroyed).
typedef std::deque<EnqueuedTask*> EnqueuedTaskQueue;
EnqueuedTaskQueue task_queue_;
base::Lock task_queue_lock_;
......
......@@ -43,13 +43,7 @@ IN_PROC_BROWSER_TEST_F(ContentBrowserTestSanityTest, Basic) {
Test();
}
#if defined(OS_MACOSX)
// This is failing on Mac ASan: http://crbug.com/394775
#define MAYBE_SingleProcess DISABLED_SingleProcess
#else
#define MAYBE_SingleProcess SingleProcess
#endif
IN_PROC_BROWSER_TEST_F(ContentBrowserTestSanityTest, MAYBE_SingleProcess) {
IN_PROC_BROWSER_TEST_F(ContentBrowserTestSanityTest, SingleProcess) {
Test();
}
......
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