Bug 1006530 - Closing a audio RTSP streaming via tab page causes system crash. r=sworkman
authorEthan Tseng <ettseng@mozilla.com>
Thu, 08 May 2014 16:16:11 +0800
changeset 182361 fcfc9fedb6b477516f779e9d4ab68c906c9d6944
parent 182360 52349bb0560b512c082fd86306e1f59b2937cb45
child 182362 9c0299e910bf110c722ad55b3f066586c3c3b4f6
push id6917
push userryanvm@gmail.com
push dateFri, 09 May 2014 13:41:22 +0000
treeherderb2g-inbound@9c0299e910bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssworkman
bugs1006530
milestone32.0a1
Bug 1006530 - Closing a audio RTSP streaming via tab page causes system crash. r=sworkman
netwerk/protocol/rtsp/controller/RtspController.cpp
netwerk/protocol/rtsp/controller/RtspController.h
netwerk/protocol/rtsp/controller/RtspControllerParent.cpp
netwerk/protocol/rtsp/controller/RtspControllerParent.h
--- a/netwerk/protocol/rtsp/controller/RtspController.cpp
+++ b/netwerk/protocol/rtsp/controller/RtspController.cpp
@@ -183,19 +183,17 @@ RtspController::GetTotalTracks(uint8_t *
 NS_IMETHODIMP
 RtspController::AsyncOpen(nsIStreamingProtocolListener *aListener)
 {
   if (!aListener) {
     LOG(("RtspController::AsyncOpen() illegal listener"));
     return NS_ERROR_NOT_INITIALIZED;
   }
 
-  // Use main thread pointer, but allow access off main thread.
-  mListener =
-    new nsMainThreadPtrHolder<nsIStreamingProtocolListener>(aListener, false);
+  mListener = aListener;
 
   if (!mURI) {
     LOG(("RtspController::AsyncOpen() illegal URI"));
     return NS_ERROR_ILLEGAL_VALUE;
   }
 
   nsAutoCString uriSpec;
   mURI->GetSpec(uriSpec);
--- a/netwerk/protocol/rtsp/controller/RtspController.h
+++ b/netwerk/protocol/rtsp/controller/RtspController.h
@@ -32,17 +32,17 @@ private:
     INIT,
     CONNECTED,
     DISCONNECTED
   };
 
   // RTSP URL refer to a stream or an aggregate of streams.
   nsCOMPtr<nsIURI> mURI;
   // The nsIStreamingProtocolListener implementation.
-  nsMainThreadPtrHandle<nsIStreamingProtocolListener> mListener;
+  nsCOMPtr<nsIStreamingProtocolListener> mListener;
   // ASCII encoded URL spec.
   nsCString mSpec;
   // Indicate the connection state between the
   // media streaming server and the Rtsp client.
   State mState;
   // Rtsp Streaming source.
   android::sp<android::RTSPSource> mRtspSource;
 };
--- a/netwerk/protocol/rtsp/controller/RtspControllerParent.cpp
+++ b/netwerk/protocol/rtsp/controller/RtspControllerParent.cpp
@@ -2,16 +2,18 @@
 /* vim: set sw=2 ts=8 et tw=80 : */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "RtspControllerParent.h"
 #include "RtspController.h"
 #include "nsIAuthPromptProvider.h"
+#include "nsThreadUtils.h"
+#include "nsProxyRelease.h"
 #include "mozilla/ipc/InputStreamUtils.h"
 #include "mozilla/ipc/URIUtils.h"
 #include "mozilla/unused.h"
 #include "nsNetUtil.h"
 #include "prlog.h"
 
 #include <sys/types.h>
 
@@ -26,19 +28,41 @@ PRLogModuleInfo* gRtspLog;
     }                                                        \
   }
 
 using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace net {
 
-NS_IMPL_ISUPPORTS(RtspControllerParent,
-                  nsIInterfaceRequestor,
-                  nsIStreamingProtocolListener)
+void
+RtspControllerParent::Destroy()
+{
+  // If we're being destroyed on a non-main thread, we AddRef again and use a
+  // proxy to release the RtspControllerParent on the main thread, where the
+  // RtspControllerParent is deleted. This ensures we only delete the
+  // RtspControllerParent on the main thread.
+  if (!NS_IsMainThread()) {
+    nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
+    NS_ENSURE_TRUE_VOID(mainThread);
+    nsRefPtr<RtspControllerParent> doomed(this);
+    if (NS_FAILED(NS_ProxyRelease(mainThread,
+            static_cast<nsIStreamingProtocolListener*>(doomed), true))) {
+      NS_WARNING("Failed to proxy release to main thread!");
+    }
+  } else {
+    delete this;
+  }
+}
+
+NS_IMPL_ADDREF(RtspControllerParent)
+NS_IMPL_RELEASE_WITH_DESTROY(RtspControllerParent, Destroy())
+NS_IMPL_QUERY_INTERFACE(RtspControllerParent,
+                        nsIInterfaceRequestor,
+                        nsIStreamingProtocolListener)
 
 RtspControllerParent::RtspControllerParent()
   : mIPCOpen(true)
   , mTotalTracks(0)
 {
 #if defined(PR_LOGGING)
   if (!gRtspLog)
     gRtspLog = PR_NewLogModule("nsRtsp");
--- a/netwerk/protocol/rtsp/controller/RtspControllerParent.h
+++ b/netwerk/protocol/rtsp/controller/RtspControllerParent.h
@@ -44,13 +44,15 @@ class RtspControllerParent : public PRts
  private:
   bool mIPCOpen;
   void ActorDestroy(ActorDestroyReason why);
   // RTSP URL refer to a stream or an aggregate of streams.
   nsCOMPtr<nsIURI> mURI;
   // The nsIStreamingProtocolController implementation.
   nsCOMPtr<nsIStreamingProtocolController> mController;
   uint32_t mTotalTracks;
+  // Ensure we are destroyed on the main thread.
+  void Destroy();
 };
 
 } // namespace net
 } // namespace mozilla
 #endif // RtspControllerParent_h