Bug 1152048 - release assert non-reentrancy of sts lock acquisition. r=honzab DONTBUILD relanding
authorNicholas Hurley <hurley@todesschaf.org>
Wed, 13 May 2015 11:13:23 -0700
changeset 246103 85e4bd6b0baad4d769f0ffd56d42dbd18b0e375b
parent 246102 71a80e43615cd6b1d4c86c23a9106cf6d780ccfb
child 246104 a00dee14032fd7b59cb9326c483f53c67a640897
push id60360
push userhurley@todesschaf.org
push dateThu, 28 May 2015 20:51:28 +0000
treeherdermozilla-inbound@85e4bd6b0baa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershonzab
bugs1152048
milestone41.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 1152048 - release assert non-reentrancy of sts lock acquisition. r=honzab DONTBUILD relanding
netwerk/base/nsSocketTransportService2.cpp
--- a/netwerk/base/nsSocketTransportService2.cpp
+++ b/netwerk/base/nsSocketTransportService2.cpp
@@ -44,16 +44,48 @@ PRThread                 *gSocketThread 
 #define BLIP_INTERVAL_PREF "network.activity.blipIntervalMilliseconds"
 #define SERVE_MULTIPLE_EVENTS_PREF "network.sts.serve_multiple_events_per_poll_iteration"
 #define MAX_TIME_BETWEEN_TWO_POLLS "network.sts.max_time_for_events_between_two_polls"
 #define TELEMETRY_PREF "toolkit.telemetry.enabled"
 
 uint32_t nsSocketTransportService::gMaxCount;
 PRCallOnceType nsSocketTransportService::gMaxCountInitOnce;
 
+class DebugMutexAutoLock
+{
+public:
+    explicit DebugMutexAutoLock(Mutex& mutex);
+    ~DebugMutexAutoLock();
+
+private:
+    Mutex *mLock;
+    static PRThread *sDebugOwningThread;
+};
+
+PRThread *DebugMutexAutoLock::sDebugOwningThread = nullptr;
+
+DebugMutexAutoLock::DebugMutexAutoLock(Mutex& mutex)
+    :mLock(&mutex)
+{
+  PRThread *currentThread = PR_GetCurrentThread();
+  MOZ_RELEASE_ASSERT(sDebugOwningThread != currentThread);
+  SOCKET_LOG(("Acquiring lock on thread %p", currentThread));
+  mLock->Lock();
+  sDebugOwningThread = currentThread;
+  SOCKET_LOG(("Acquired lock on thread %p", currentThread));
+}
+
+DebugMutexAutoLock::~DebugMutexAutoLock()
+{
+  sDebugOwningThread = nullptr;
+  mLock->Unlock();
+  mLock = nullptr;
+  SOCKET_LOG(("Released lock on thread %p", PR_GetCurrentThread()));
+}
+
 //-----------------------------------------------------------------------------
 // ctor/dtor (called on the main/UI thread by the service manager)
 
 nsSocketTransportService::nsSocketTransportService()
     : mThread(nullptr)
     , mThreadEvent(nullptr)
     , mAutodialEnabled(false)
     , mLock("nsSocketTransportService::mLock")
@@ -109,17 +141,17 @@ nsSocketTransportService::~nsSocketTrans
 }
 
 //-----------------------------------------------------------------------------
 // event queue (any thread)
 
 already_AddRefed<nsIThread>
 nsSocketTransportService::GetThreadSafely()
 {
-    MutexAutoLock lock(mLock);
+    DebugMutexAutoLock lock(mLock);
     nsCOMPtr<nsIThread> result = mThread;
     return result.forget();
 }
 
 NS_IMETHODIMP
 nsSocketTransportService::Dispatch(nsIRunnable *event, uint32_t flags)
 {
     SOCKET_LOG(("STS dispatch [%p]\n", event));
@@ -483,17 +515,17 @@ nsSocketTransportService::Init()
         }
     }
 
     nsCOMPtr<nsIThread> thread;
     nsresult rv = NS_NewThread(getter_AddRefs(thread), this);
     if (NS_FAILED(rv)) return rv;
     
     {
-        MutexAutoLock lock(mLock);
+        DebugMutexAutoLock lock(mLock);
         // Install our mThread, protecting against concurrent readers
         thread.swap(mThread);
     }
 
     nsCOMPtr<nsIPrefBranch> tmpPrefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
     if (tmpPrefService) {
         tmpPrefService->AddObserver(SEND_BUFFER_PREF, this, false);
         tmpPrefService->AddObserver(KEEPALIVE_ENABLED_PREF, this, false);
@@ -526,30 +558,30 @@ nsSocketTransportService::Shutdown()
 
     if (!mInitialized)
         return NS_OK;
 
     if (mShuttingDown)
         return NS_ERROR_UNEXPECTED;
 
     {
-        MutexAutoLock lock(mLock);
+        DebugMutexAutoLock lock(mLock);
 
         // signal the socket thread to shutdown
         mShuttingDown = true;
 
         if (mThreadEvent)
             PR_SetPollableEvent(mThreadEvent);
         // else wait for Poll timeout
     }
 
     // join with thread
     mThread->Shutdown();
     {
-        MutexAutoLock lock(mLock);
+        DebugMutexAutoLock lock(mLock);
         // Drop our reference to mThread and make sure that any concurrent
         // readers are excluded
         mThread = nullptr;
     }
 
     nsCOMPtr<nsIPrefBranch> tmpPrefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
     if (tmpPrefService) 
         tmpPrefService->RemoveObserver(SEND_BUFFER_PREF, this);
@@ -575,17 +607,17 @@ nsSocketTransportService::GetOffline(boo
 {
     *offline = mOffline;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSocketTransportService::SetOffline(bool offline)
 {
-    MutexAutoLock lock(mLock);
+    DebugMutexAutoLock lock(mLock);
     if (!mOffline && offline) {
         // signal the socket thread to go offline, so it will detach sockets
         mGoingOffline = true;
         mOffline = true;
     }
     else if (mOffline && !offline) {
         mOffline = false;
     }
@@ -708,17 +740,17 @@ nsSocketTransportService::SetAutodialEna
 {
     mAutodialEnabled = value;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSocketTransportService::OnDispatchedEvent(nsIThreadInternal *thread)
 {
-    MutexAutoLock lock(mLock);
+    DebugMutexAutoLock lock(mLock);
     if (mThreadEvent)
         PR_SetPollableEvent(mThreadEvent);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSocketTransportService::OnProcessNextEvent(nsIThreadInternal *thread,
                                              bool mayWait, uint32_t depth)
@@ -888,17 +920,17 @@ nsSocketTransportService::Run()
                     thread->HasPendingEvents(&pendingEvents);
                 }
             }
         } while (pendingEvents);
 
         bool goingOffline = false;
         // now that our event queue is empty, check to see if we should exit
         {
-            MutexAutoLock lock(mLock);
+            DebugMutexAutoLock lock(mLock);
             if (mShuttingDown) {
                 if (mTelemetryEnabledPref &&
                     !startOfCycleForLastCycleCalc.IsNull()) {
                     Telemetry::Accumulate(
                         Telemetry::STS_NUMBER_OF_PENDING_EVENTS_IN_THE_LAST_CYCLE,
                         numberOfPendingEventsLastCycle);
                     Telemetry::AccumulateTimeDelta(
                         Telemetry::STS_POLL_AND_EVENT_THE_LAST_CYCLE,
@@ -1085,17 +1117,17 @@ nsSocketTransportService::DoPollIteratio
             if (PR_WaitForPollableEvent(mThreadEvent) != PR_SUCCESS) {
                 // On Windows, the TCP loopback connection in the
                 // pollable event may become broken when a laptop
                 // switches between wired and wireless networks or
                 // wakes up from hibernation.  We try to create a
                 // new pollable event.  If that fails, we fall back
                 // on "busy wait".
                 {
-                    MutexAutoLock lock(mLock);
+                    DebugMutexAutoLock lock(mLock);
                     PR_DestroyPollableEvent(mThreadEvent);
                     mThreadEvent = PR_NewPollableEvent();
                 }
                 if (!mThreadEvent) {
                     NS_WARNING("running socket transport thread without "
                                "a pollable event");
                     SOCKET_LOG(("running socket transport thread without "
                          "a pollable event"));