Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions src/process_win32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,27 @@ struct ProcessHandle
CloseHandle(process_handle);
}
};
// =============================================================================
// Job Object for child process cleanup
// =============================================================================

// Singleton job object that kills all child processes when parent exits.
// Using JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE ensures spawned servers die
// when the client process terminates (even abnormally).
static HANDLE get_child_process_job()
{
static HANDLE job = []() -> HANDLE {
HANDLE h = CreateJobObjectA(nullptr, nullptr);
if (h)
{
JOBOBJECT_EXTENDED_LIMIT_INFORMATION info = {};
info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
SetInformationJobObject(h, JobObjectExtendedLimitInformation, &info, sizeof(info));
}
return h;
}();
return job;
}

// =============================================================================
// Helper functions
Expand Down Expand Up @@ -520,6 +541,11 @@ void Process::spawn(
handle_->process_id = pi.dwProcessId;
handle_->running = true;

// Assign to job object so child dies when parent dies
HANDLE job = get_child_process_job();
if (job)
AssignProcessToJobObject(job, pi.hProcess);

stdin_->handle_->handle = stdin_write;
stdout_->handle_->handle = stdout_read;
stderr_->handle_->handle = stderr_read;
Expand Down