Bug 1036629 - Take a deathgrip on the runnable passed to NS_DispatchToCurrentThread. r=bsmedberg
authorAndrew McCreight <continuation@gmail.com>
Tue, 15 Jul 2014 14:29:14 -0700
changeset 216177 724724630cc956b57694906275ab7e13b44d5008
parent 216176 452d8502bea14bcf6e08db0585bde526349182e2
child 216178 cd3ee2c040e19bde5ff9fdc4105918f648c3fb75
push id515
push userraliiev@mozilla.com
push dateMon, 06 Oct 2014 12:51:51 +0000
treeherdermozilla-release@267c7a481bef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg
bugs1036629
milestone33.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 1036629 - Take a deathgrip on the runnable passed to NS_DispatchToCurrentThread. r=bsmedberg This will prevent a leak of the runnable if it is passed in with a refcount of zero and the dispatch fails.
xpcom/glue/nsThreadUtils.cpp
--- a/xpcom/glue/nsThreadUtils.cpp
+++ b/xpcom/glue/nsThreadUtils.cpp
@@ -134,34 +134,43 @@ NS_IsMainThread()
     do_GetService(NS_THREADMANAGER_CONTRACTID);
   if (mgr) {
     mgr->GetIsMainThread(&result);
   }
   return bool(result);
 }
 #endif
 
+// It is common to call NS_DispatchToCurrentThread with a newly
+// allocated runnable with a refcount of zero. To keep us from leaking
+// the runnable if the dispatch method fails, we take a death grip.
 NS_METHOD
 NS_DispatchToCurrentThread(nsIRunnable* aEvent)
 {
+  nsCOMPtr<nsIRunnable> deathGrip = aEvent;
 #ifdef MOZILLA_INTERNAL_API
   nsIThread* thread = NS_GetCurrentThread();
   if (!thread) {
     return NS_ERROR_UNEXPECTED;
   }
 #else
   nsCOMPtr<nsIThread> thread;
   nsresult rv = NS_GetCurrentThread(getter_AddRefs(thread));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 #endif
   return thread->Dispatch(aEvent, NS_DISPATCH_NORMAL);
 }
 
+// In the case of failure with a newly allocated runnable with a
+// refcount of zero, we intentionally leak the runnable, because it is
+// likely that the runnable is being dispatched to the main thread
+// because it owns main thread only objects, so it is not safe to
+// release them here.
 NS_METHOD
 NS_DispatchToMainThread(nsIRunnable* aEvent, uint32_t aDispatchFlags)
 {
   nsCOMPtr<nsIThread> thread;
   nsresult rv = NS_GetMainThread(getter_AddRefs(thread));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }