Bug 1534776 - Don't leak the world if the shell's main() exits early. r=jwalden
authorJason Orendorff <jorendorff@mozilla.com>
Wed, 20 Mar 2019 19:20:06 +0000
changeset 465298 57833afcf11dcb15f1f5b900aae14fd11910807a
parent 465297 4c580575e563a9370aafa332757e1e1a13292f42
child 465299 ac8f4708f0993be72073b3f785db9b7f14ec8f6f
push id112496
push usershindli@mozilla.com
push dateThu, 21 Mar 2019 04:37:39 +0000
treeherdermozilla-inbound@29476d3ca61d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwalden
bugs1534776
milestone68.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 1534776 - Don't leak the world if the shell's main() exits early. r=jwalden This changes the order of some cleanup operations, harmlessly, to make initialization and teardown more FIFO. Differential Revision: https://phabricator.services.mozilla.com/D23222
js/src/shell/js.cpp
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -11176,24 +11176,36 @@ int main(int argc, char** argv, char** e
   size_t nurseryBytes = JS::DefaultNurseryBytes;
   nurseryBytes = op.getIntOption("nursery-size") * 1024L * 1024L;
 
   /* Use the same parameters as the browser in xpcjsruntime.cpp. */
   JSContext* cx = JS_NewContext(JS::DefaultHeapMaxBytes, nurseryBytes);
   if (!cx) {
     return 1;
   }
+  auto destroyCx = MakeScopeExit([cx] { JS_DestroyContext(cx); });
 
   UniquePtr<ShellContext> sc = MakeUnique<ShellContext>(cx);
   if (!sc) {
     return 1;
   }
+  auto destroyShellContext = MakeScopeExit([cx, &sc] {
+    // Must clear out some of sc's pointer containers before JS_DestroyContext.
+    sc->markObservers.reset();
+
+    JS_SetContextPrivate(cx, nullptr);
+    sc.reset();
+  });
 
   JS_SetContextPrivate(cx, sc.get());
   JS_SetGrayGCRootsTracer(cx, TraceGrayRoots, nullptr);
+  auto resetGrayGCRootsTracer = MakeScopeExit([cx] {
+    JS_SetGrayGCRootsTracer(cx, nullptr, nullptr);
+  });
+
   // Waiting is allowed on the shell's main thread, for now.
   JS_SetFutexCanWait(cx);
   JS::SetWarningReporter(cx, WarningReporter);
   if (!SetContextOptions(cx, op)) {
     return 1;
   }
 
   JS_SetGCParameter(cx, JSGC_MAX_BYTES, 0xffffffff);
@@ -11225,16 +11237,23 @@ int main(int argc, char** argv, char** e
       cx, ForwardingPromiseRejectionTrackerCallback);
 
   JS_SetNativeStackQuota(cx, gMaxStackSize);
 
   JS::dbg::SetDebuggerMallocSizeOf(cx, moz_malloc_size_of);
 
   js::UseInternalJobQueues(cx);
 
+  auto shutdownShellThreads = MakeScopeExit([cx] {
+    KillWatchdog(cx);
+    KillWorkerThreads(cx);
+    DestructSharedObjectMailbox();
+    CancelOffThreadJobsForRuntime(cx);
+  });
+
   if (const char* opt = op.getStringOption("nursery-strings")) {
     if (strcmp(opt, "on") == 0) {
       cx->runtime()->gc.nursery().enableStrings();
     } else if (strcmp(opt, "off") == 0) {
       cx->runtime()->gc.nursery().disableStrings();
     } else {
       MOZ_CRASH("invalid option value for --nursery-strings, must be on/off");
     }
@@ -11270,26 +11289,10 @@ int main(int argc, char** argv, char** e
   result = Shell(cx, &op, envp);
 
 #ifdef DEBUG
   if (OOM_printAllocationCount) {
     printf("OOM max count: %" PRIu64 "\n", js::oom::simulator.counter());
   }
 #endif
 
-  JS_SetGrayGCRootsTracer(cx, nullptr, nullptr);
-
-  // Must clear out some of sc's pointer containers before JS_DestroyContext.
-  sc->markObservers.reset();
-
-  KillWatchdog(cx);
-
-  KillWorkerThreads(cx);
-
-  DestructSharedObjectMailbox();
-
-  CancelOffThreadJobsForRuntime(cx);
-
-  JS_SetContextPrivate(cx, nullptr);
-  sc.reset();
-  JS_DestroyContext(cx);
   return result;
 }