Bug 1301246: Allow processes to break away from their job. r=mhowell
authorKris Maglione <maglione.k@gmail.com>
Thu, 08 Sep 2016 12:26:13 -0700
changeset 313367 ce6190b497023911c060af11dae5d3afe2df4a71
parent 313366 af1a3c41d8c139f070a553f1125b106cea3d596d
child 313368 411e2e9f694a8b5b3d6b9f21bcfc33c38396e2fa
push id30679
push usercbook@mozilla.com
push dateFri, 09 Sep 2016 10:03:06 +0000
treeherdermozilla-central@feff79e5b137 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmhowell
bugs1301246
milestone51.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 1301246: Allow processes to break away from their job. r=mhowell MozReview-Commit-ID: IFyK7HkQP35
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
@@ -18,16 +18,18 @@ var win32 = {
   WINAPI: ctypes.winapi_abi,
 
   VOID: ctypes.void_t,
 
   BYTE: ctypes.uint8_t,
   WORD: ctypes.uint16_t,
   DWORD: ctypes.uint32_t,
   LONG: ctypes.long,
+  LARGE_INTEGER: ctypes.int64_t,
+  ULONGLONG: ctypes.uint64_t,
 
   UINT: ctypes.unsigned_int,
   UCHAR: ctypes.unsigned_char,
 
   BOOL: ctypes.bool,
 
   HANDLE: ctypes.voidptr_t,
   PVOID: ctypes.voidptr_t,
@@ -90,27 +92,64 @@ Object.assign(win32, {
 
   PIPE_WAIT: 0x00,
   PIPE_NOWAIT: 0x01,
 
   STILL_ACTIVE: 259,
 
   PROC_THREAD_ATTRIBUTE_HANDLE_LIST: 0x00020002,
 
+  JobObjectBasicLimitInformation: 2,
+  JobObjectExtendedLimitInformation: 9,
+
+  JOB_OBJECT_LIMIT_BREAKAWAY_OK: 0x00000800,
+
   // These constants are 32-bit unsigned integers, but Windows defines
   // them as negative integers cast to an unsigned type.
   STD_INPUT_HANDLE: -10 + 0x100000000,
   STD_OUTPUT_HANDLE: -11 + 0x100000000,
   STD_ERROR_HANDLE: -12 + 0x100000000,
 
   WAIT_TIMEOUT: 0x00000102,
   WAIT_FAILED: 0xffffffff,
 });
 
 Object.assign(win32, {
+  JOBOBJECT_BASIC_LIMIT_INFORMATION: new ctypes.StructType("JOBOBJECT_BASIC_LIMIT_INFORMATION", [
+    {"PerProcessUserTimeLimit": win32.LARGE_INTEGER},
+    {"PerJobUserTimeLimit": win32.LARGE_INTEGER},
+    {"LimitFlags": win32.DWORD},
+    {"MinimumWorkingSetSize": win32.SIZE_T},
+    {"MaximumWorkingSetSize": win32.SIZE_T},
+    {"ActiveProcessLimit": win32.DWORD},
+    {"Affinity": win32.ULONG_PTR},
+    {"PriorityClass": win32.DWORD},
+    {"SchedulingClass": win32.DWORD},
+  ]),
+
+  IO_COUNTERS: new ctypes.StructType("IO_COUNTERS", [
+    {"ReadOperationCount": win32.ULONGLONG},
+    {"WriteOperationCount": win32.ULONGLONG},
+    {"OtherOperationCount": win32.ULONGLONG},
+    {"ReadTransferCount": win32.ULONGLONG},
+    {"WriteTransferCount": win32.ULONGLONG},
+    {"OtherTransferCount": win32.ULONGLONG},
+  ]),
+});
+
+Object.assign(win32, {
+  JOBOBJECT_EXTENDED_LIMIT_INFORMATION: new ctypes.StructType("JOBOBJECT_EXTENDED_LIMIT_INFORMATION", [
+    {"BasicLimitInformation": win32.JOBOBJECT_BASIC_LIMIT_INFORMATION},
+    {"IoInfo": win32.IO_COUNTERS},
+    {"ProcessMemoryLimit": win32.SIZE_T},
+    {"JobMemoryLimit": win32.SIZE_T},
+    {"PeakProcessMemoryUsed": win32.SIZE_T},
+    {"PeakJobMemoryUsed": win32.SIZE_T},
+  ]),
+
   OVERLAPPED: new ctypes.StructType("OVERLAPPED", [
      {"Internal": win32.ULONG_PTR},
      {"InternalHigh": win32.ULONG_PTR},
      {"Offset": win32.DWORD},
      {"OffsetHigh": win32.DWORD},
      {"hEvent": win32.HANDLE},
   ]),
 
@@ -334,16 +373,25 @@ var libc = new Library("libc", LIBC_CHOI
   ],
 
   ResumeThread: [
     win32.WINAPI,
     win32.DWORD,
     win32.HANDLE, /* hThread */
   ],
 
+  SetInformationJobObject: [
+    win32.WINAPI,
+    win32.BOOL,
+    win32.HANDLE, /* hJob */
+    ctypes.int, /* JobObjectInfoClass */
+    win32.LPVOID, /* lpJobObjectInfo */
+    win32.DWORD, /* cbJobObjectInfoLengt */
+  ],
+
   TerminateJobObject: [
     win32.WINAPI,
     win32.BOOL,
     win32.HANDLE, /* hJob */
     win32.UINT, /* uExitCode */
   ],
 
   TerminateProcess: [
--- a/toolkit/modules/subprocess/subprocess_worker_win.js
+++ b/toolkit/modules/subprocess/subprocess_worker_win.js
@@ -494,16 +494,27 @@ class Process extends BaseProcess {
     }
 
     if (threadAttrs) {
       libc.DeleteProcThreadAttributeList(threadAttrs);
     }
 
     if (ok) {
       this.jobHandle = win32.Handle(libc.CreateJobObjectW(null, null));
+
+      let info = win32.JOBOBJECT_EXTENDED_LIMIT_INFORMATION();
+      info.BasicLimitInformation.LimitFlags = win32.JOB_OBJECT_LIMIT_BREAKAWAY_OK;
+
+      ok = libc.SetInformationJobObject(this.jobHandle, win32.JobObjectExtendedLimitInformation,
+                                        ctypes.cast(info.address(), ctypes.voidptr_t),
+                                        info.constructor.size);
+      errorMessage = `Failed to set job limits: 0x${(ctypes.winLastError || 0).toString(16)}`;
+    }
+
+    if (ok) {
       ok = libc.AssignProcessToJobObject(this.jobHandle, procInfo.hProcess);
       errorMessage = `Failed to attach process to job object: 0x${(ctypes.winLastError || 0).toString(16)}`;
     }
 
     if (!ok) {
       for (let pipe of this.pipes) {
         pipe.close();
       }