From f14583321de65500957b16d70ccb3b44a43923b8 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Mon, 31 Aug 2026 23:49:47 +0000 Subject: [PATCH] Use stable Windows process handles for job assignment --- docs/roadmap/implementation.md | 2 +- .../subprocess/process_tree_windows.go | 22 +++++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index a5a2a18..ea7116b 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -273,7 +273,7 @@ error presentation at the existing adapter-facing boundary. ## Stage 3 — Use The Stable Windows Process Handle -**Status: Pending** +**Status: Completed** ### Goal diff --git a/internal/adapters/subprocess/process_tree_windows.go b/internal/adapters/subprocess/process_tree_windows.go index e3fb6e4..2ddad2c 100644 --- a/internal/adapters/subprocess/process_tree_windows.go +++ b/internal/adapters/subprocess/process_tree_windows.go @@ -39,19 +39,23 @@ func (tree *windowsProcessTree) Start(cmd *exec.Cmd) error { return err } - process, err := windows.OpenProcess(windows.PROCESS_SET_QUOTA|windows.PROCESS_TERMINATE, false, uint32(cmd.Process.Pid)) - if err == nil { - err = windows.AssignProcessToJobObject(job, process) - _ = windows.CloseHandle(process) + var assignErr error + withHandleErr := cmd.Process.WithHandle(func(handle uintptr) { + assignErr = windows.AssignProcessToJobObject(job, windows.Handle(handle)) + }) + if withHandleErr == nil && assignErr == nil { + assignErr = resumeInitialThread(uint32(cmd.Process.Pid)) } - if err == nil { - err = resumeInitialThread(uint32(cmd.Process.Pid)) - } - if err != nil { + if withHandleErr != nil || assignErr != nil { killErr := cmd.Process.Kill() waitErr := cmd.Wait() _ = windows.CloseHandle(job) - return joinErrors(fmt.Errorf("assign process to job object: %w", err), killErr, waitErr) + return joinErrors( + fmt.Errorf("acquire process handle for job assignment: %w", withHandleErr), + fmt.Errorf("assign process to job object or resume initial thread: %w", assignErr), + killErr, + waitErr, + ) } tree.job = job