Bug 1414310 - Destroy shell buffer stream state before calling JS_ShutDown r=sfink
authorJon Coppeard <jcoppeard@mozilla.com>
Thu, 09 Nov 2017 15:02:24 +0000
changeset 444261 94d45591fe6002cf19259cc2fd80a4a394831d36
parent 444260 7b993d1dbe5faad163d3449fa94f97d6668c4466
child 444262 21cfd71761e89ac83fb84bc80fa08a56aff8c4ce
push id1618
push userCallek@gmail.com
push dateThu, 11 Jan 2018 17:45:48 +0000
treeherdermozilla-release@882ca853e05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink
bugs1414310
milestone58.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 1414310 - Destroy shell buffer stream state before calling JS_ShutDown r=sfink
js/src/shell/js.cpp
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -5668,17 +5668,17 @@ struct BufferStreamState
     {}
 
     ~BufferStreamState()
     {
         MOZ_ASSERT(jobs.empty());
     }
 };
 
-static ExclusiveWaitableData<BufferStreamState> bufferStreamState(mutexid::BufferStreamState);
+static ExclusiveWaitableData<BufferStreamState>* bufferStreamState;
 
 static void
 BufferStreamMain(BufferStreamJob* job)
 {
     const uint8_t* const bytes = job->bytes.begin();
 
     size_t byteOffset = 0;
     while (true) {
@@ -5686,17 +5686,17 @@ BufferStreamMain(BufferStreamJob* job)
             job->consumer->streamClosed(JS::StreamConsumer::EndOfFile);
             break;
         }
 
         bool shutdown;
         size_t delayMillis;
         size_t chunkSize;
         {
-            auto state = bufferStreamState.lock();
+            auto state = bufferStreamState->lock();
             shutdown = state->shutdown;
             delayMillis = state->delayMillis;
             chunkSize = state->chunkSize;
         }
 
         if (shutdown) {
             job->consumer->streamClosed(JS::StreamConsumer::Error);
             break;
@@ -5707,17 +5707,17 @@ BufferStreamMain(BufferStreamJob* job)
         chunkSize = Min(chunkSize, job->bytes.length() - byteOffset);
 
         if (!job->consumer->consumeChunk(bytes + byteOffset, chunkSize))
             break;
 
         byteOffset += chunkSize;
     }
 
-    auto state = bufferStreamState.lock();
+    auto state = bufferStreamState->lock();
     size_t jobIndex = 0;
     while (state->jobs[jobIndex].get() != job)
         jobIndex++;
     job->thread.detach();  // quiet assert in ~Thread() called by erase().
     state->jobs.erase(state->jobs.begin() + jobIndex);
     if (state->jobs.empty())
         state.notify_all(/* jobs empty */);
 }
@@ -5736,17 +5736,17 @@ ConsumeBufferSource(JSContext* cx, JS::H
     if (!job || !job->bytes.resize(byteLength))
         return false;
 
     memcpy(job->bytes.begin(), dataPointer.unwrap(), byteLength);
 
     BufferStreamJob* jobPtr = job.get();
 
     {
-        auto state = bufferStreamState.lock();
+        auto state = bufferStreamState->lock();
         MOZ_ASSERT(!state->shutdown);
         if (!state->jobs.append(Move(job)))
             return false;
     }
 
     return jobPtr->thread.init(BufferStreamMain, jobPtr);
 }
 
@@ -5761,25 +5761,35 @@ SetBufferStreamParams(JSContext* cx, uns
     if (!ToNumber(cx, args[0], &delayMillis))
         return false;
 
     double chunkSize;
     if (!ToNumber(cx, args[1], &chunkSize))
         return false;
 
     {
-        auto state = bufferStreamState.lock();
+        auto state = bufferStreamState->lock();
         state->delayMillis = delayMillis;
         state->chunkSize = chunkSize;
     }
 
     args.rval().setUndefined();
     return true;
 }
 
+static void
+ShutdownBufferStreams()
+{
+    auto state = bufferStreamState->lock();
+    state->shutdown = true;
+    while (!state->jobs.empty())
+        state.wait(/* jobs empty */);
+    state->jobs.clearAndFree();
+}
+
 class SprintOptimizationTypeInfoOp : public JS::ForEachTrackedOptimizationTypeInfoOp
 {
     Sprinter* sp;
     bool startedTypes_;
     bool hadError_;
 
   public:
     explicit SprintOptimizationTypeInfoOp(Sprinter* sp)
@@ -8623,24 +8633,16 @@ PreInit()
 #endif
 }
 
 int
 main(int argc, char** argv, char** envp)
 {
     PreInit();
 
-    auto shutdownBufferStreams = MakeScopeExit([] {
-        auto state = bufferStreamState.lock();
-        state->shutdown = true;
-        while (!state->jobs.empty())
-            state.wait(/* jobs empty */);
-        state->jobs.clearAndFree();
-    });
-
     sArgc = argc;
     sArgv = argv;
 
     int result;
 
 #ifdef HAVE_SETLOCALE
     setlocale(LC_ALL, "");
 #endif
@@ -8923,16 +8925,25 @@ main(int argc, char** argv, char** envp)
 
     JS_SetTrustedPrincipals(cx, &ShellPrincipals::fullyTrusted);
     JS_SetSecurityCallbacks(cx, &ShellPrincipals::securityCallbacks);
     JS_InitDestroyPrincipalsCallback(cx, ShellPrincipals::destroy);
 
     JS_AddInterruptCallback(cx, ShellInterruptCallback);
     JS::SetBuildIdOp(cx, ShellBuildId);
     JS::SetAsmJSCacheOps(cx, &asmJSCacheOps);
+
+    bufferStreamState =
+        js_new<ExclusiveWaitableData<BufferStreamState>>(mutexid::BufferStreamState);
+    if (!bufferStreamState)
+        return 1;
+    auto shutdownBufferStreams = MakeScopeExit([] {
+        ShutdownBufferStreams();
+        js_delete(bufferStreamState);
+    });
     JS::InitConsumeStreamCallback(cx, ConsumeBufferSource);
 
     gOffThreadState = js_new<OffThreadState>();
     if (!gOffThreadState)
         return 1;
     auto deleteOffThreadState = MakeScopeExit([] {
         js_delete(gOffThreadState);
     });