aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/spawn.c
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2024-10-19 21:32:04 +0300
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2024-10-19 21:32:04 +0300
commit3b3bc070f802491e98f87d9191e7d33fec78dd5a (patch)
tree6272d10949276351e442b5a7ded304b89bf2b75b /src/spawn.c
parent62b124e77493e32fe7f516bcb7dfbd454f353499 (diff)
downloadsciteco-3b3bc070f802491e98f87d9191e7d33fec78dd5a.tar.gz
<EC>: perhaps fixed race conditions and problems when creating and terminating process groups on Win32
* Sometimes already the job assignment failed in CI builds. We now check whether the process is still alive before throwing an error. * We now set the JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE flag. This theoretically shouldn't be necessary when using TerminateJobObject(), but who knows.
Diffstat (limited to 'src/spawn.c')
-rw-r--r--src/spawn.c28
1 files changed, 24 insertions, 4 deletions
diff --git a/src/spawn.c b/src/spawn.c
index e6d620c..a1b8ac8 100644
--- a/src/spawn.c
+++ b/src/spawn.c
@@ -294,15 +294,35 @@ teco_state_execute_done(teco_machine_main_t *ctx, const teco_string_t *str, GErr
teco_spawn_ctx.interrupted = FALSE;
#ifdef G_OS_WIN32
+ teco_spawn_ctx.pid = CreateJobObject(NULL, NULL);
+ if (!teco_spawn_ctx.pid) {
+ teco_error_win32_set(error, "Cannot create job object", GetLastError());
+ goto gerror;
+ }
+ JOBOBJECT_EXTENDED_LIMIT_INFORMATION job_info = {
+ .BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
+ };
+ if (!SetInformationJobObject(teco_spawn_ctx.pid, JobObjectExtendedLimitInformation,
+ &job_info, sizeof(job_info))) {
+ CloseHandle(teco_spawn_ctx.pid);
+ teco_error_win32_set(error, "Cannot configure job object", GetLastError());
+ goto gerror;
+ }
/*
* Assigning the process to a job object will allow us to
* kill the entire process tree relatively easily and without
* race conditions.
+ * There can however be a race condition while assigning the
+ * job object since the process could already be dead.
*/
- teco_spawn_ctx.pid = CreateJobObjectA(NULL, NULL);
- if (!teco_spawn_ctx.pid || !AssignProcessToJobObject(teco_spawn_ctx.pid, pid)) {
- g_set_error(error, TECO_ERROR, TECO_ERROR_FAILED,
- "Cannot assign process to job object (%lu)", GetLastError());
+ DWORD exit_code;
+ if (!AssignProcessToJobObject(teco_spawn_ctx.pid, pid) &&
+ (GetLastError() != ERROR_ACCESS_DENIED ||
+ !GetExitCodeProcess(teco_spawn_ctx.pid, &exit_code) ||
+ exit_code == STILL_ACTIVE)) {
+ CloseHandle(teco_spawn_ctx.pid);
+ teco_error_win32_set(error, "Cannot assign process to job object",
+ GetLastError());
goto gerror;
}