Bug 1208957 - Join the watchdog thread to avoid shutdown races. r=billm a=gchang
authorBlake Kaplan <mrbkap@gmail.com>
Tue, 14 Mar 2017 23:27:21 -0700
changeset 379147 bb2c60d68d506b1bb11d413c21fabfe6c749fbfc
parent 379146 c826f1b2bc2403030516ce16166d129f08df4c89
child 379148 ca09f7a332eee99846274cec552688a692c23b3e
push id1419
push userjlund@mozilla.com
push dateMon, 10 Apr 2017 20:44:07 +0000
treeherdermozilla-release@5e6801b73ef6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm, gchang
bugs1208957
milestone53.0
Bug 1208957 - Join the watchdog thread to avoid shutdown races. r=billm a=gchang MozReview-Commit-ID: FlnPO2fJWVu
js/xpconnect/src/XPCJSContext.cpp
--- a/js/xpconnect/src/XPCJSContext.cpp
+++ b/js/xpconnect/src/XPCJSContext.cpp
@@ -953,19 +953,22 @@ class Watchdog
             NS_RUNTIMEABORT("PR_NewLock failed.");
         mWakeup = PR_NewCondVar(mLock);
         if (!mWakeup)
             NS_RUNTIMEABORT("PR_NewCondVar failed.");
 
         {
             AutoLockWatchdog lock(this);
 
+            // Gecko uses thread private for accounting and has to clean up at thread exit.
+            // Therefore, even though we don't have a return value from the watchdog, we need to
+            // join it on shutdown.
             mThread = PR_CreateThread(PR_USER_THREAD, WatchdogMain, this,
                                       PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
-                                      PR_UNJOINABLE_THREAD, 0);
+                                      PR_JOINABLE_THREAD, 0);
             if (!mThread)
                 NS_RUNTIMEABORT("PR_CreateThread failed!");
 
             // WatchdogMain acquires the lock and then asserts mInitialized. So
             // make sure to set mInitialized before releasing the lock here so
             // that it's atomic with the creation of the thread.
             mInitialized = true;
         }
@@ -982,16 +985,18 @@ class Watchdog
             mShuttingDown = true;
 
             // Wake up the watchdog, and wait for it to call us back.
             PR_NotifyCondVar(mWakeup);
             PR_WaitCondVar(mWakeup, PR_INTERVAL_NO_TIMEOUT);
             MOZ_ASSERT(!mShuttingDown);
         }
 
+        PR_JoinThread(mThread);
+
         // Destroy state.
         mThread = nullptr;
         PR_DestroyCondVar(mWakeup);
         mWakeup = nullptr;
         PR_DestroyLock(mLock);
         mLock = nullptr;
 
         // All done.