fix: enforce durable Windows launch release barrier
This commit is contained in:
@@ -188,7 +188,9 @@ func (manager *execSupervisor) Start(ctx context.Context, spec supervisor.StartS
|
||||
return fail(fmt.Errorf("create suspended command process: %w", err))
|
||||
}
|
||||
// The child owns these handles after CreateProcessAsUser returns. Keep only
|
||||
// the three parent ends and the process/job handles in the daemon.
|
||||
// the three parent ends and the process/job handles in the daemon. The
|
||||
// primary thread remains suspended until the executor has durably recorded
|
||||
// launch authorization and calls Process.Release.
|
||||
_ = stdinRead.Close()
|
||||
_ = stdoutWrite.Close()
|
||||
_ = stderrWrite.Close()
|
||||
@@ -198,14 +200,19 @@ func (manager *execSupervisor) Start(ctx context.Context, spec supervisor.StartS
|
||||
_ = winapi.CloseHandle(processInfo.Thread)
|
||||
return fail(fmt.Errorf("assign command to Job: %w", err))
|
||||
}
|
||||
if _, err := winapi.ResumeThread(processInfo.Thread); err != nil {
|
||||
_ = winapi.TerminateJobObject(job, 1)
|
||||
_ = winapi.CloseHandle(processInfo.Process)
|
||||
_ = winapi.CloseHandle(processInfo.Thread)
|
||||
return fail(fmt.Errorf("release suspended command: %w", err))
|
||||
}
|
||||
pipesTransferred = true
|
||||
_ = winapi.CloseHandle(processInfo.Thread)
|
||||
var threadClosed sync.Once
|
||||
closeThread := func() {
|
||||
threadClosed.Do(func() { _ = winapi.CloseHandle(processInfo.Thread) })
|
||||
}
|
||||
releaseFn := func() error {
|
||||
if _, err := winapi.ResumeThread(processInfo.Thread); err != nil {
|
||||
closeThread()
|
||||
return fmt.Errorf("release suspended command: %w", err)
|
||||
}
|
||||
closeThread()
|
||||
return nil
|
||||
}
|
||||
started := manager.options.Now()
|
||||
handles := &nativeHandles{process: processInfo.Process, job: job, pid: processInfo.ProcessId}
|
||||
cleanupJob = false
|
||||
@@ -216,6 +223,7 @@ func (manager *execSupervisor) Start(ctx context.Context, spec supervisor.StartS
|
||||
if err := winapi.GetExitCodeProcess(processInfo.Process, &code); err != nil && waitErr == nil {
|
||||
waitErr = err
|
||||
}
|
||||
closeThread()
|
||||
handles.close.Do(func() {
|
||||
_ = winapi.CloseHandle(processInfo.Process)
|
||||
_ = winapi.CloseHandle(job)
|
||||
@@ -223,9 +231,11 @@ func (manager *execSupervisor) Start(ctx context.Context, spec supervisor.StartS
|
||||
return int32(code), false, waitErr
|
||||
}
|
||||
killFn := func(code uint32) error {
|
||||
return winapi.TerminateJobObject(job, code)
|
||||
err := winapi.TerminateJobObject(job, code)
|
||||
closeThread()
|
||||
return err
|
||||
}
|
||||
process := manager.registerProcess(spec.IssueUUID, identity, command, stdinWrite, stdoutRead, stderrRead, started, waitFn, killFn, cleanup)
|
||||
process := manager.registerProcess(spec.IssueUUID, identity, command, stdinWrite, stdoutRead, stderrRead, started, waitFn, killFn, releaseFn, cleanup)
|
||||
process.snapshotFn = func() (supervisor.ResourceSnapshot, error) {
|
||||
return queryJobSnapshot(job, manager.options.Now())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user