Bug 1370027: Part 1 - Cleanly handle a subprocess child being reaped by NSPR. r=aswan
authorKris Maglione <maglione.k@gmail.com>
Tue, 06 Jun 2017 16:00:53 -0700
changeset 410860 f4f2dab8b32338f937a3661946809df4674440d6
parent 410859 196bfa86b5a63c20f7f6fdf3e30d9ff3d8839de3
child 410861 0d16a08bbcfa181535789a43856ef176cc9829c8
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaswan
bugs1370027
milestone55.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 1370027: Part 1 - Cleanly handle a subprocess child being reaped by NSPR. r=aswan The first time any other code in the parent process uses NSPR (usually via nsIProcess) to spawn a new process, it spawns a thread to contuously wait for any child process to exit. This thread winds up reaping our child processes before we get the chance to wait for them, which leads us to continuously poll for them to exit. We don't have a good way to handle this, but checking the error status of waitpid at least prevents us from failing catastrophically. MozReview-Commit-ID: 75Z1yUHUmjy
dom/system/OSFileConstants.cpp
toolkit/modules/subprocess/subprocess_worker_unix.js
--- a/dom/system/OSFileConstants.cpp
+++ b/dom/system/OSFileConstants.cpp
@@ -542,16 +542,17 @@ static const dom::ConstantSpec gLibcProp
   // error values
   INT_CONSTANT(EACCES),
   INT_CONSTANT(EAGAIN),
   INT_CONSTANT(EBADF),
   INT_CONSTANT(EEXIST),
   INT_CONSTANT(EFAULT),
   INT_CONSTANT(EFBIG),
   INT_CONSTANT(EINVAL),
+  INT_CONSTANT(EINTR),
   INT_CONSTANT(EIO),
   INT_CONSTANT(EISDIR),
 #if defined(ELOOP) // not defined with VC9
   INT_CONSTANT(ELOOP),
 #endif // defined(ELOOP)
   INT_CONSTANT(EMFILE),
   INT_CONSTANT(ENAMETOOLONG),
   INT_CONSTANT(ENFILE),
--- a/toolkit/modules/subprocess/subprocess_worker_unix.js
+++ b/toolkit/modules/subprocess/subprocess_worker_unix.js
@@ -460,29 +460,35 @@ class Process extends BaseProcess {
   wait() {
     if (this.exitCode !== null) {
       return this.exitCode;
     }
 
     let status = ctypes.int();
 
     let res = libc.waitpid(this.pid, status.address(), LIBC.WNOHANG);
-    if (res == this.pid) {
-      let sig = unix.WTERMSIG(status.value);
-      if (sig) {
-        this.exitCode = -sig;
-      } else {
-        this.exitCode = unix.WEXITSTATUS(status.value);
-      }
+    // If there's a failure here and we get any errno other than EINTR, it
+    // means that the process has been reaped by another thread (most likely
+    // the nspr process wait thread), and its actual exit status is not
+    // available to us. In that case, we have to assume success.
+    if (res == 0 || (res == -1 && ctypes.errno == LIBC.EINTR)) {
+      return null;
+    }
 
-      this.fd.dispose();
-      io.updatePollFds();
-      this.resolveExit(this.exitCode);
-      return this.exitCode;
+    let sig = unix.WTERMSIG(status.value);
+    if (sig) {
+      this.exitCode = -sig;
+    } else {
+      this.exitCode = unix.WEXITSTATUS(status.value);
     }
+
+    this.fd.dispose();
+    io.updatePollFds();
+    this.resolveExit(this.exitCode);
+    return this.exitCode;
   }
 }
 
 io = {
   pollFds: null,
   pollHandlers: null,
 
   pipes: new Map(),