summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2021-04-16 19:22:16 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2021-04-16 19:22:16 -0400
commitb8c5d256646130067cc6f2d4db676dc2173522ac (patch)
tree648f0e781c05bfda84efca78307e73c626250214
parented3adc7e99c23d5f12b36ab162b5c8489f25a2d8 (diff)
fix process_kill on windows
-rw-r--r--main.c2
-rw-r--r--process-win.c80
-rw-r--r--windows_installer/ted/ted/ted.vdproj6
3 files changed, 55 insertions, 33 deletions
diff --git a/main.c b/main.c
index 3a1b686..8cf3997 100644
--- a/main.c
+++ b/main.c
@@ -1,5 +1,3 @@
-// @TODO:
-// - terminate process not working on windows?
#include "base.h"
no_warn_start
#if _WIN32
diff --git a/process-win.c b/process-win.c
index d36302b..d7ff4b2 100644
--- a/process-win.c
+++ b/process-win.c
@@ -2,6 +2,7 @@
struct Process {
HANDLE pipe_read, pipe_write;
+ HANDLE job;
PROCESS_INFORMATION process_info;
char error[200];
};
@@ -15,7 +16,9 @@ static void get_last_error_str(char *out, size_t out_sz) {
}
bool process_run(Process *process, char const *command) {
- // thanks to https://stackoverflow.com/a/35658917
+ // thanks to https://stackoverflow.com/a/35658917 for the pipe code
+ // thanks to https://devblogs.microsoft.com/oldnewthing/20131209-00/?p=2433 for the job code
+
bool success = false;
memset(process, 0, sizeof *process);
char *command_line = str_dup(command);
@@ -23,35 +26,57 @@ bool process_run(Process *process, char const *command) {
strbuf_printf(process->error, "Out of memory.");
return false;
}
- HANDLE pipe_read, pipe_write;
- SECURITY_ATTRIBUTES security_attrs = {sizeof(SECURITY_ATTRIBUTES)};
- security_attrs.bInheritHandle = TRUE;
- if (CreatePipe(&pipe_read, &pipe_write, &security_attrs, 0)) {
- STARTUPINFOA startup = {sizeof(STARTUPINFOA)};
- startup.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
- startup.hStdOutput = pipe_write;
- startup.hStdError = pipe_write;
- startup.wShowWindow = SW_HIDE;
-
- if (CreateProcessA(NULL, command_line, NULL, NULL, TRUE, CREATE_NEW_CONSOLE,
- NULL, NULL, &startup, &process->process_info)) {
- process->pipe_read = pipe_read;
- process->pipe_write = pipe_write;
- success = true;
+ // we need to create a "job" for this, because apparently when you kill a process on windows,
+ // all its children just keep going. so cmd.exe would die, but not the actual build process.
+ // jobs fix this, apparently.
+ HANDLE job = CreateJobObjectA(NULL, NULL);
+ if (job) {
+ JOBOBJECT_EXTENDED_LIMIT_INFORMATION job_info = {0};
+ job_info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
+ SetInformationJobObject(job, JobObjectExtendedLimitInformation, &job_info, sizeof job_info);
+ HANDLE pipe_read, pipe_write;
+ SECURITY_ATTRIBUTES security_attrs = {sizeof(SECURITY_ATTRIBUTES)};
+ security_attrs.bInheritHandle = TRUE;
+ if (CreatePipe(&pipe_read, &pipe_write, &security_attrs, 0)) {
+ STARTUPINFOA startup = {sizeof(STARTUPINFOA)};
+ startup.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
+ startup.hStdOutput = pipe_write;
+ startup.hStdError = pipe_write;
+ startup.wShowWindow = SW_HIDE;
+ PROCESS_INFORMATION *process_info = &process->process_info;
+ if (CreateProcessA(NULL, command_line, NULL, NULL, TRUE, CREATE_NEW_CONSOLE | CREATE_SUSPENDED,
+ NULL, NULL, &startup, process_info)) {
+ // create a suspended process, add it to the job, then resume (unsuspend) the process
+ if (AssignProcessToJobObject(job, process_info->hProcess)) {
+ if (ResumeThread(process_info->hThread) != (DWORD)-1) {
+ process->job = job;
+ process->pipe_read = pipe_read;
+ process->pipe_write = pipe_write;
+ success = true;
+ }
+ }
+ if (!success) {
+ TerminateProcess(process_info->hProcess, 1);
+ CloseHandle(process_info->hProcess);
+ CloseHandle(process_info->hThread);
+ }
+ } else {
+ char buf[150];
+ get_last_error_str(buf, sizeof buf);
+ strbuf_printf(process->error, "Couldn't run `%s`: %s", command, buf);
+ }
+ free(command_line);
+ if (!success) {
+ CloseHandle(pipe_read);
+ CloseHandle(pipe_write);
+ }
} else {
char buf[150];
get_last_error_str(buf, sizeof buf);
- strbuf_printf(process->error, "Couldn't run `%s`: %s", command, buf);
+ strbuf_printf(process->error, "Couldn't create pipe: %s", buf);
}
- free(command_line);
- if (!success) {
- CloseHandle(pipe_read);
- CloseHandle(pipe_write);
- }
- } else {
- char buf[150];
- get_last_error_str(buf, sizeof buf);
- strbuf_printf(process->error, "Couldn't create pipe: %s", buf);
+ if (!success)
+ CloseHandle(job);
}
return success;
}
@@ -78,8 +103,7 @@ long long process_read(Process *process, char *data, size_t size) {
}
void process_kill(Process *process) {
- TerminateProcess(process->process_info.hProcess, 1);
- TerminateThread(process->process_info.hThread, 1);
+ CloseHandle(process->job);
CloseHandle(process->pipe_read);
CloseHandle(process->pipe_write);
CloseHandle(process->process_info.hProcess);
diff --git a/windows_installer/ted/ted/ted.vdproj b/windows_installer/ted/ted/ted.vdproj
index c2dba5e..960f7dd 100644
--- a/windows_installer/ted/ted/ted.vdproj
+++ b/windows_installer/ted/ted/ted.vdproj
@@ -505,15 +505,15 @@
{
"Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:ted"
- "ProductCode" = "8:{E281ABEA-14D0-46C5-AFDB-BFF6F6617B3F}"
- "PackageCode" = "8:{E3D40FEF-9758-436F-8B50-E63C8A309848}"
+ "ProductCode" = "8:{C8992411-A410-4770-BBCD-8FE8281C599B}"
+ "PackageCode" = "8:{E11A6787-F72C-47F3-9975-DF24587F89E3}"
"UpgradeCode" = "8:{844F6C2B-DF3B-4A81-9BD5-603401BBA651}"
"AspNetVersion" = "8:2.0.50727.0"
"RestartWWWService" = "11:FALSE"
"RemovePreviousVersions" = "11:TRUE"
"DetectNewerInstalledVersion" = "11:FALSE"
"InstallAllUsers" = "11:FALSE"
- "ProductVersion" = "8:21.03.1809"
+ "ProductVersion" = "8:21.04.1619"
"Manufacturer" = "8:ted"
"ARPHELPTELEPHONE" = "8:"
"ARPHELPLINK" = "8:"