From bfbaf508a72edf6815e7859035a3f962318ac12e Mon Sep 17 00:00:00 2001 From: "stoyan@chromium.org" Date: Fri, 26 Feb 2010 17:24:10 +0000 Subject: Destroy pending tasks marshaled through windows messages avoiding possible crashes when object is destroyed and there is tasks in the queue. BUG=none TEST=none Review URL: http://codereview.chromium.org/661145 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@40125 0039d316-1c4b-4281-b951-d872f2087c98 --- chrome_frame/chrome_frame_delegate.h | 37 ++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'chrome_frame') diff --git a/chrome_frame/chrome_frame_delegate.h b/chrome_frame/chrome_frame_delegate.h index 11eaa30..93d4645 100644 --- a/chrome_frame/chrome_frame_delegate.h +++ b/chrome_frame/chrome_frame_delegate.h @@ -7,7 +7,9 @@ #include #include +#include +#include "base/lock.h" #include "chrome/test/automation/automation_messages.h" #include "ipc/ipc_message.h" @@ -125,15 +127,35 @@ class TaskMarshaller { template class TaskMarshallerThroughWindowsMessages : public TaskMarshaller { public: + TaskMarshallerThroughWindowsMessages() {} virtual void PostTask(const tracked_objects::Location& from_here, Task* task) { task->SetBirthPlace(from_here); T* this_ptr = static_cast(this); if (this_ptr->IsWindow()) { this_ptr->AddRef(); + PushTask(task); this_ptr->PostMessage(MSG_EXECUTE_TASK, reinterpret_cast(task)); } else { DLOG(INFO) << "Dropping MSG_EXECUTE_TASK message for destroyed window."; + delete task; + } + } + + + protected: + ~TaskMarshallerThroughWindowsMessages() { + DeleteAllPendingTasks(); + } + + void DeleteAllPendingTasks() { + AutoLock lock(lock_); + DLOG_IF(INFO, !pending_tasks_.empty()) << "Destroying " << + pending_tasks_.size() << " pending tasks"; + while (!pending_tasks_.empty()) { + Task* task = pending_tasks_.front(); + pending_tasks_.pop(); + delete task; } } @@ -146,12 +168,27 @@ template class TaskMarshallerThroughWindowsMessages inline LRESULT ExecuteTask(UINT, WPARAM wparam, LPARAM, BOOL& handled) { // NOLINT Task* task = reinterpret_cast(wparam); + PopTask(task); task->Run(); delete task; T* this_ptr = static_cast(this); this_ptr->Release(); return 0; } + + inline void PushTask(Task* task) { + AutoLock lock(lock_); + pending_tasks_.push(task); + } + + inline void PopTask(Task* task) { + AutoLock lock(lock_); + DCHECK_EQ(task, pending_tasks_.front()); + pending_tasks_.pop(); + } + + Lock lock_; + std::queue pending_tasks_; }; #endif // CHROME_FRAME_CHROME_FRAME_DELEGATE_H_ -- cgit v1.1