Bug 1119060: Ensure that PluginProcessParent::mLaunchCompleteTask is non-null until the runnable has executed; r=gfritzsche
authorAaron Klotz <aklotz@mozilla.com>
Wed, 07 Jan 2015 18:01:51 -0700
changeset 248636 06402d84ac3d38c86214129c533911a520165e58
parent 248635 20a7f674d668fdd19e0337f6f5847befc3a66fbf
child 248637 7877a00d7025405b31b2f0df73e8a1067bda5923
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgfritzsche
bugs1119060
milestone37.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1119060: Ensure that PluginProcessParent::mLaunchCompleteTask is non-null until the runnable has executed; r=gfritzsche
dom/plugins/ipc/PluginProcessParent.cpp
dom/plugins/ipc/PluginProcessParent.h
--- a/dom/plugins/ipc/PluginProcessParent.cpp
+++ b/dom/plugins/ipc/PluginProcessParent.cpp
@@ -106,46 +106,63 @@ PluginProcessParent::Delete()
 }
 
 void
 PluginProcessParent::SetCallRunnableImmediately(bool aCallImmediately)
 {
     mRunCompleteTaskImmediately = aCallImmediately;
 }
 
+/**
+ * This function exists so that we may provide an additional level of
+ * indirection between the task being posted to main event loop (a
+ * RunnableMethod) and the launch complete task itself. This is needed
+ * for cases when both WaitUntilConnected or OnChannel* race to invoke the
+ * task.
+ */
+void
+PluginProcessParent::RunLaunchCompleteTask()
+{
+    if (mLaunchCompleteTask) {
+        mLaunchCompleteTask->Run();
+        mLaunchCompleteTask = nullptr;
+    }
+}
+
 bool
 PluginProcessParent::WaitUntilConnected(int32_t aTimeoutMs)
 {
     bool result = GeckoChildProcessHost::WaitUntilConnected(aTimeoutMs);
     if (mRunCompleteTaskImmediately && mLaunchCompleteTask) {
         if (result) {
             mLaunchCompleteTask->SetLaunchSucceeded();
         }
-        mLaunchCompleteTask->Run();
-        mLaunchCompleteTask = nullptr;
+        RunLaunchCompleteTask();
     }
     return result;
 }
 
 void
 PluginProcessParent::OnChannelConnected(int32_t peer_pid)
 {
     GeckoChildProcessHost::OnChannelConnected(peer_pid);
     if (mLaunchCompleteTask && !mRunCompleteTaskImmediately) {
         mLaunchCompleteTask->SetLaunchSucceeded();
-        mMainMsgLoop->PostTask(FROM_HERE, mLaunchCompleteTask.release());
+        mMainMsgLoop->PostTask(FROM_HERE, NewRunnableMethod(this,
+                                   &PluginProcessParent::RunLaunchCompleteTask));
     }
 }
 
 void
 PluginProcessParent::OnChannelError()
 {
     GeckoChildProcessHost::OnChannelError();
     if (mLaunchCompleteTask && !mRunCompleteTaskImmediately) {
-        mMainMsgLoop->PostTask(FROM_HERE, mLaunchCompleteTask.release());
+        mMainMsgLoop->PostTask(FROM_HERE, NewRunnableMethod(this,
+                                   &PluginProcessParent::RunLaunchCompleteTask));
     }
 }
 
 bool
 PluginProcessParent::IsConnected()
 {
     mozilla::MonitorAutoLock lock(mMonitor);
     return mProcessState == PROCESS_CONNECTED;
--- a/dom/plugins/ipc/PluginProcessParent.h
+++ b/dom/plugins/ipc/PluginProcessParent.h
@@ -69,16 +69,18 @@ public:
     virtual bool WaitUntilConnected(int32_t aTimeoutMs = 0) MOZ_OVERRIDE;
 
     virtual void OnChannelConnected(int32_t peer_pid) MOZ_OVERRIDE;
     virtual void OnChannelError() MOZ_OVERRIDE;
 
     bool IsConnected();
 
 private:
+    void RunLaunchCompleteTask();
+
     std::string mPluginFilePath;
     UniquePtr<LaunchCompleteTask> mLaunchCompleteTask;
     MessageLoop* mMainMsgLoop;
     bool mRunCompleteTaskImmediately;
 
     DISALLOW_EVIL_CONSTRUCTORS(PluginProcessParent);
 };