package windows import ( "context" "fmt" "time" ) type pidWaitHandle interface { Wait(time.Duration) (bool, error) Close() error } type pidOpener func(int) (pidWaitHandle, error) func waitForProcessExit(ctx context.Context, pid int, timeout time.Duration, open pidOpener) error { if pid <= 0 { return fmt.Errorf("process PID must be positive") } if timeout <= 0 { return fmt.Errorf("process wait timeout must be positive") } handle, err := open(pid) if err != nil { return fmt.Errorf("open process %d: %w", pid, err) } defer handle.Close() deadline := time.NewTimer(timeout) defer deadline.Stop() for { if err := ctx.Err(); err != nil { return err } exited, err := handle.Wait(250 * time.Millisecond) if err != nil { return fmt.Errorf("wait for process %d: %w", pid, err) } if exited { return nil } select { case <-ctx.Done(): return ctx.Err() case <-deadline.C: return context.DeadlineExceeded default: } } }