Bug 1371548: Accept invalid stderr handles when spawning subprocesses. r=aswan
authorKris Maglione <maglione.k@gmail.com>
Sat, 10 Jun 2017 16:35:14 -0700
changeset 411526 f7987c98de3ecb90a07e58a1337e10ae2d83bb4e
parent 411525 b18762d91f3fe1d6c828e6657189811b67b7548a
child 411527 042829191d730dd6e901d09fb62bbf4274fe5895
child 411557 16fbe02d5cb57907929b7ace9c443c184f57ceba
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
bugs1371548
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 1371548: Accept invalid stderr handles when spawning subprocesses. r=aswan MozReview-Commit-ID: B8FKavo7ksT
toolkit/modules/subprocess/subprocess_shared_win.js
toolkit/modules/subprocess/subprocess_worker_win.js
--- a/toolkit/modules/subprocess/subprocess_shared_win.js
+++ b/toolkit/modules/subprocess/subprocess_shared_win.js
@@ -64,16 +64,19 @@ Object.assign(win32, {
 
 Object.assign(win32, {
   LPCSTR: win32.LPSTR,
   LPCWSTR: win32.LPWSTR,
   LPCVOID: win32.LPVOID,
 });
 
 Object.assign(win32, {
+  INVALID_HANDLE_VALUE: ctypes.cast(ctypes.int64_t(-1), win32.HANDLE),
+  NULL_HANDLE_VALUE: ctypes.cast(ctypes.uintptr_t(0), win32.HANDLE),
+
   CREATE_SUSPENDED: 0x00000004,
   CREATE_NEW_CONSOLE: 0x00000010,
   CREATE_UNICODE_ENVIRONMENT: 0x00000400,
   CREATE_NO_WINDOW: 0x08000000,
   CREATE_BREAKAWAY_FROM_JOB: 0x01000000,
   EXTENDED_STARTUPINFO_PRESENT: 0x00080000,
 
   STARTF_USESTDHANDLES: 0x0100,
--- a/toolkit/modules/subprocess/subprocess_worker_win.js
+++ b/toolkit/modules/subprocess/subprocess_worker_win.js
@@ -375,24 +375,30 @@ class Process extends BaseProcess {
     } else {
       let srcHandle;
       if (stderr == "stdout") {
         srcHandle = their_pipes[1];
       } else {
         srcHandle = libc.GetStdHandle(win32.STD_ERROR_HANDLE);
       }
 
-      let handle = win32.HANDLE();
+      // If we don't have a valid stderr handle, just pass it along without duplicating.
+      if (String(srcHandle) == win32.INVALID_HANDLE_VALUE ||
+          String(srcHandle) == win32.NULL_HANDLE_VALUE) {
+        their_pipes[2] = srcHandle;
+      } else {
+        let handle = win32.HANDLE();
 
-      let curProc = libc.GetCurrentProcess();
-      let ok = libc.DuplicateHandle(curProc, srcHandle, curProc, handle.address(),
-                                    0, true /* inheritable */,
-                                    win32.DUPLICATE_SAME_ACCESS);
+        let curProc = libc.GetCurrentProcess();
+        let ok = libc.DuplicateHandle(curProc, srcHandle, curProc, handle.address(),
+                                      0, true /* inheritable */,
+                                      win32.DUPLICATE_SAME_ACCESS);
 
-      their_pipes[2] = ok && win32.Handle(handle);
+        their_pipes[2] = ok && win32.Handle(handle);
+      }
     }
 
     if (!their_pipes.every(handle => handle)) {
       throw new Error("Failed to create pipe");
     }
 
     this.pipes = our_pipes;
 
@@ -497,17 +503,20 @@ class Process extends BaseProcess {
       null, /* Security attributes */
       null, /* Thread security attributes */
       true, /* Inherits handles */
       processFlags, envp, options.workdir,
       startupInfo.address(),
       procInfo.address());
 
     for (let handle of new Set(handles)) {
-      handle.dispose();
+      // If any of our handles are invalid, they don't have finalizers.
+      if (handle && handle.dispose) {
+        handle.dispose();
+      }
     }
 
     if (threadAttrs) {
       libc.DeleteProcThreadAttributeList(threadAttrs);
     }
 
     if (ok) {
       this.jobHandle = win32.Handle(libc.CreateJobObjectW(null, null));