Bug 1099339 - Handle SuspendThread failure more gracefully (r=me)
authorLuke Wagner <luke@mozilla.com>
Sat, 15 Nov 2014 03:41:59 -0600
changeset 240198 d1903414198f3255cfbaa579981384afb5496529
parent 240197 25dfe9824b6f18dffaee00e51514a1cfe7a8c488
child 240199 b892bd18e0d923cafb676a2dc1dc33e992992a04
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersme
bugs1099339
milestone36.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 1099339 - Handle SuspendThread failure more gracefully (r=me)
js/src/asmjs/AsmJSSignalHandlers.cpp
js/src/vm/Runtime.cpp
--- a/js/src/asmjs/AsmJSSignalHandlers.cpp
+++ b/js/src/asmjs/AsmJSSignalHandlers.cpp
@@ -963,18 +963,18 @@ js::EnsureSignalHandlersInstalled(JSRunt
     if (IsSignalHandlingBroken())
         return false;
 # endif
 #endif
 
 #if defined(XP_WIN)
     // Windows uses SuspendThread to stop the main thread from another thread,
     // so the only handler we need is for asm.js out-of-bound faults.
-    if (!AddVectoredExceptionHandler(/* FirstHandler = */true, AsmJSFaultHandler))
-        MOZ_CRASH("unable to install vectored exception handler");
+    if (!AddVectoredExceptionHandler(/* FirstHandler = */ true, AsmJSFaultHandler))
+        return false;
 #else
     // The interrupt handler allows the main thread to be paused from another
     // thread (see InterruptRunningJitCode).
     struct sigaction interruptHandler;
     interruptHandler.sa_flags = SA_SIGINFO;
     interruptHandler.sa_sigaction = &JitInterruptHandler;
     sigemptyset(&interruptHandler.sa_mask);
     struct sigaction prev;
@@ -1034,33 +1034,29 @@ js::InterruptRunningJitCode(JSRuntime *r
         RedirectIonBackedgesToInterruptCheck(rt);
         return;
     }
 
     // We are not on the runtime's main thread, so to do 1 and 2 above, we need
     // to halt the runtime's main thread first.
 #if defined(XP_WIN)
     // On Windows, we can simply suspend the main thread and work directly on
-    // its context from this thread.
+    // its context from this thread. SuspendThread can sporadically fail if the
+    // thread is in the middle of a syscall. Rather than retrying in a loop,
+    // just wait for the next request for interrupt.
     HANDLE thread = (HANDLE)rt->ownerThreadNative();
-    if (SuspendThread(thread) == -1)
-        MOZ_CRASH("Failed to suspend main thread");
-
-    CONTEXT context;
-    context.ContextFlags = CONTEXT_CONTROL;
-    if (!GetThreadContext(thread, &context))
-        MOZ_CRASH("Failed to get suspended thread context");
-
-    RedirectJitCodeToInterruptCheck(rt, &context);
-
-    if (!SetThreadContext(thread, &context))
-        MOZ_CRASH("Failed to set suspended thread context");
-
-    if (ResumeThread(thread) == -1)
-        MOZ_CRASH("Failed to resume main thread");
+    if (SuspendThread(thread) != -1) {
+        CONTEXT context;
+        context.ContextFlags = CONTEXT_CONTROL;
+        if (GetThreadContext(thread, &context)) {
+            RedirectJitCodeToInterruptCheck(rt, &context);
+            SetThreadContext(thread, &context);
+        }
+        ResumeThread(thread);
+    }
 #else
     // On Unix, we instead deliver an async signal to the main thread which
     // halts the thread and callers our JitInterruptHandler (which has already
     // been installed by EnsureSignalHandlersInstalled).
     pthread_t thread = (pthread_t)rt->ownerThreadNative();
     pthread_kill(thread, sInterruptSignal);
 #endif
 }
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -257,17 +257,17 @@ JSRuntime::init(uint32_t maxbytes, uint3
     ownerThread_ = PR_GetCurrentThread();
 
     // Get a platform-native handle for the owner thread, used by
     // js::InterruptRunningJitCode to halt the runtime's main thread.
 #ifdef XP_WIN
     size_t openFlags = THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME;
     HANDLE self = OpenThread(openFlags, false, GetCurrentThreadId());
     if (!self)
-        MOZ_CRASH("Unable to open thread handle");
+        return false;
     static_assert(sizeof(HANDLE) <= sizeof(ownerThreadNative_), "need bigger field");
     ownerThreadNative_ = (size_t)self;
 #else
     static_assert(sizeof(pthread_t) <= sizeof(ownerThreadNative_), "need bigger field");
     ownerThreadNative_ = (size_t)pthread_self();
 #endif
 
     exclusiveAccessLock = PR_NewLock();