Skip to content

Commit 19cdd6f

Browse files
committed
fix: ensure child processes die when parent exits (Windows)
Add Job Object with JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE flag to automatically terminate spawned child processes when the client process terminates, even if it crashes or is killed. This prevents orphaned server processes.
1 parent 257e0e3 commit 19cdd6f

1 file changed

Lines changed: 26 additions & 0 deletions

File tree

src/process_win32.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,27 @@ struct ProcessHandle
5555
CloseHandle(process_handle);
5656
}
5757
};
58+
// =============================================================================
59+
// Job Object for child process cleanup
60+
// =============================================================================
61+
62+
// Singleton job object that kills all child processes when parent exits.
63+
// Using JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE ensures spawned servers die
64+
// when the client process terminates (even abnormally).
65+
static HANDLE get_child_process_job()
66+
{
67+
static HANDLE job = []() -> HANDLE {
68+
HANDLE h = CreateJobObjectA(nullptr, nullptr);
69+
if (h)
70+
{
71+
JOBOBJECT_EXTENDED_LIMIT_INFORMATION info = {};
72+
info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
73+
SetInformationJobObject(h, JobObjectExtendedLimitInformation, &info, sizeof(info));
74+
}
75+
return h;
76+
}();
77+
return job;
78+
}
5879

5980
// =============================================================================
6081
// Helper functions
@@ -520,6 +541,11 @@ void Process::spawn(
520541
handle_->process_id = pi.dwProcessId;
521542
handle_->running = true;
522543

544+
// Assign to job object so child dies when parent dies
545+
HANDLE job = get_child_process_job();
546+
if (job)
547+
AssignProcessToJobObject(job, pi.hProcess);
548+
523549
stdin_->handle_->handle = stdin_write;
524550
stdout_->handle_->handle = stdout_read;
525551
stderr_->handle_->handle = stderr_read;

0 commit comments

Comments
 (0)