Bug 997286: Make NS_NewNamedThread safe if the event tries to commit suicide r=bsmedberg
authorRandell Jesup <rjesup@jesup.org>
Wed, 16 Apr 2014 16:39:16 -0400
changeset 197347 ed17d9bbe15ca1bc9b4bc6ce2f786a2de88b0323
parent 197346 8cbd6019a24aaebb6264520c7cb6670210a17c97
child 197348 95e6b5e31ce1ee3900f3d5a6dd0041e264669765
push id3624
push userasasaki@mozilla.com
push dateMon, 09 Jun 2014 21:49:01 +0000
treeherdermozilla-beta@b1a5da15899a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg
bugs997286
milestone31.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 997286: Make NS_NewNamedThread safe if the event tries to commit suicide r=bsmedberg
content/media/AudioStream.cpp
xpcom/glue/nsThreadUtils.h
--- a/content/media/AudioStream.cpp
+++ b/content/media/AudioStream.cpp
@@ -407,17 +407,18 @@ AudioStream::Init(int32_t aNumChannels, 
   NS_ABORT_IF_FALSE(bufferLimit % mBytesPerFrame == 0, "Must buffer complete frames");
   mBuffer.SetCapacity(bufferLimit);
 
   if (aLatencyRequest == LowLatency) {
     // Don't block this thread to initialize a cubeb stream.
     // When this is done, it will start callbacks from Cubeb.  Those will
     // cause us to move from INITIALIZED to RUNNING.  Until then, we
     // can't access any cubeb functions.
-    AudioInitTask *init = new AudioInitTask(this, aLatencyRequest, params);
+    // Use a RefPtr to avoid leaks if Dispatch fails
+    RefPtr<AudioInitTask> init = new AudioInitTask(this, aLatencyRequest, params);
     init->Dispatch();
     return NS_OK;
   }
   // High latency - open synchronously
   nsresult rv = OpenCubeb(params, aLatencyRequest);
   // See if we need to start() the stream, since we must do that from this
   // thread for now (cubeb API issue)
   CheckForStart();
--- a/xpcom/glue/nsThreadUtils.h
+++ b/xpcom/glue/nsThreadUtils.h
@@ -65,25 +65,29 @@ NS_NewThread(nsIThread **result,
  */
 template <size_t LEN>
 inline NS_METHOD
 NS_NewNamedThread(const char (&name)[LEN],
                   nsIThread **result,
                   nsIRunnable *initialEvent = nullptr,
                   uint32_t stackSize = nsIThreadManager::DEFAULT_STACK_SIZE)
 {
-  nsresult rv = NS_NewThread(result, nullptr, stackSize);
+  // Hold a ref while dispatching the initial event to match NS_NewThread()
+  nsCOMPtr<nsIThread> thread;
+  nsresult rv = NS_NewThread(getter_AddRefs(thread), nullptr, stackSize);
   if (NS_WARN_IF(NS_FAILED(rv)))
     return rv;
-  NS_SetThreadName<LEN>(*result, name);
+  NS_SetThreadName<LEN>(thread, name);
   if (initialEvent) {
-    rv = (*result)->Dispatch(initialEvent, NS_DISPATCH_NORMAL);
+    rv = thread->Dispatch(initialEvent, NS_DISPATCH_NORMAL);
     NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Initial event dispatch failed");
   }
 
+  *result = nullptr;
+  thread.swap(*result);
   return rv;
 }
 
 /**
  * Get a reference to the current thread.
  *
  * @param result
  *   The resulting nsIThread object.