--- a/toolkit/modules/subprocess/subprocess_shared_win.js
+++ b/toolkit/modules/subprocess/subprocess_shared_win.js
@@ -59,16 +59,17 @@ Object.assign(win32, {
Object.assign(win32, {
LPCSTR: win32.LPSTR,
LPCWSTR: win32.LPWSTR,
LPCVOID: win32.LPVOID,
});
Object.assign(win32, {
+ CREATE_SUSPENDED: 0x00000004,
CREATE_NEW_CONSOLE: 0x00000010,
CREATE_UNICODE_ENVIRONMENT: 0x00000400,
EXTENDED_STARTUPINFO_PRESENT: 0x00080000,
CREATE_NO_WINDOW: 0x08000000,
STARTF_USESTDHANDLES: 0x0100,
DUPLICATE_CLOSE_SOURCE: 0x01,
@@ -151,16 +152,23 @@ Object.assign(win32, {
STARTUPINFOEXW: new ctypes.StructType("STARTUPINFOEXW", [
{"StartupInfo": win32.STARTUPINFOW},
{"lpAttributeList": win32.LPPROC_THREAD_ATTRIBUTE_LIST},
]),
});
var libc = new Library("libc", LIBC_CHOICES, {
+ AssignProcessToJobObject: [
+ win32.WINAPI,
+ win32.BOOL,
+ win32.HANDLE, /* hJob */
+ win32.HANDLE, /* hProcess */
+ ],
+
CloseHandle: [
win32.WINAPI,
win32.BOOL,
win32.HANDLE, /* hObject */
],
CreateEventW: [
win32.WINAPI,
@@ -178,16 +186,23 @@ var libc = new Library("libc", LIBC_CHOI
win32.DWORD, /* dwDesiredAccess */
win32.DWORD, /* dwShareMode */
win32.SECURITY_ATTRIBUTES.ptr, /* opt lpSecurityAttributes */
win32.DWORD, /* dwCreationDisposition */
win32.DWORD, /* dwFlagsAndAttributes */
win32.HANDLE, /* opt hTemplateFile */
],
+ CreateJobObjectW: [
+ win32.WINAPI,
+ win32.HANDLE,
+ win32.SECURITY_ATTRIBUTES.ptr, /* opt lpJobAttributes */
+ win32.LPWSTR, /* lpName */
+ ],
+
CreateNamedPipeW: [
win32.WINAPI,
win32.HANDLE,
win32.LPWSTR, /* lpName */
win32.DWORD, /* dwOpenMode */
win32.DWORD, /* dwPipeMode */
win32.DWORD, /* nMaxInstances */
win32.DWORD, /* nOutBufferSize */
@@ -312,16 +327,29 @@ var libc = new Library("libc", LIBC_CHOI
ReleaseSemaphore: [
win32.WINAPI,
win32.BOOL,
win32.HANDLE, /* hSemaphore */
win32.LONG, /* lReleaseCount */
win32.LONG.ptr, /* opt out lpPreviousCount */
],
+ ResumeThread: [
+ win32.WINAPI,
+ win32.DWORD,
+ win32.HANDLE, /* hThread */
+ ],
+
+ TerminateJobObject: [
+ win32.WINAPI,
+ win32.BOOL,
+ win32.HANDLE, /* hJob */
+ win32.UINT, /* uExitCode */
+ ],
+
TerminateProcess: [
win32.WINAPI,
win32.BOOL,
win32.HANDLE, /* hProcess */
win32.UINT, /* uExitCode */
],
UpdateProcThreadAttribute: [
--- a/toolkit/modules/subprocess/subprocess_worker_win.js
+++ b/toolkit/modules/subprocess/subprocess_worker_win.js
@@ -331,17 +331,17 @@ class Process extends BaseProcess {
return this.handle;
}
/**
* Forcibly terminates the process.
*/
kill() {
this.killed = true;
- libc.TerminateProcess(this.handle, TERMINATE_EXIT_CODE);
+ libc.TerminateJobObject(this.jobHandle, TERMINATE_EXIT_CODE);
}
/**
* Initializes the IO pipes for use as standard input, output, and error
* descriptors in the spawned process.
*
* @returns {win32.Handle[]}
* The array of file handles belonging to the spawned process.
@@ -443,16 +443,17 @@ class Process extends BaseProcess {
args = args.map(arg => this.quoteString(arg));
let envp = this.stringList(options.environment);
let handles = this.initPipes(options);
let processFlags = win32.CREATE_NO_WINDOW
+ | win32.CREATE_SUSPENDED
| win32.CREATE_UNICODE_ENVIRONMENT;
let startupInfoEx = new win32.STARTUPINFOEXW();
let startupInfo = startupInfoEx.StartupInfo;
startupInfo.cb = win32.STARTUPINFOW.size;
startupInfo.dwFlags = win32.STARTF_USESTDHANDLES;
@@ -494,20 +495,24 @@ class Process extends BaseProcess {
if (!ok) {
for (let pipe of this.pipes) {
pipe.close();
}
throw new Error("Failed to create process");
}
- libc.CloseHandle(procInfo.hThread);
-
this.handle = win32.Handle(procInfo.hProcess);
this.pid = procInfo.dwProcessId;
+
+ this.jobHandle = win32.Handle(libc.CreateJobObjectW(null, null));
+ libc.AssignProcessToJobObject(this.jobHandle, this.handle);
+
+ libc.ResumeThread(procInfo.hThread);
+ libc.CloseHandle(procInfo.hThread);
}
/**
* Called when our process handle is signaled as active, meaning the process
* has exited.
*/
onReady() {
this.wait();
@@ -537,16 +542,20 @@ class Process extends BaseProcess {
}
this.resolveExit(exitCode);
this.exitCode = exitCode;
this.handle.dispose();
this.handle = null;
+ libc.TerminateJobObject(this.jobHandle, TERMINATE_EXIT_CODE);
+ this.jobHandle.dispose();
+ this.jobHandle = null;
+
for (let pipe of this.pipes) {
pipe.maybeClose();
}
io.updatePollEvents();
return exitCode;
}