Close piped processes on cancellation

This commit is contained in:
2026-11-02 03:16:36 +00:00
parent 9c02ed769b
commit 595745c7b1
6 changed files with 150 additions and 1 deletions

View File

@@ -55,6 +55,8 @@ type PipedProcess struct {
stdout io.ReadCloser
parent context.Context
cancel context.CancelFunc
stopIO func() bool
ioDone <-chan struct{}
waitOnce sync.Once
waitErr error
}
@@ -80,6 +82,9 @@ func (child *PipedProcess) Cancel() {
func (child *PipedProcess) Wait() error {
child.waitOnce.Do(func() {
err := child.command.Wait()
if !child.stopIO() {
<-child.ioDone
}
child.cancel()
if err == nil {
return
@@ -121,12 +126,20 @@ func StartPiped(ctx context.Context, invocation Invocation) (*PipedProcess, erro
cancel()
return nil, fmt.Errorf("start %q: %w", invocation.Args[0], err)
}
done := make(chan struct{})
stopIO := context.AfterFunc(childContext, func() {
defer close(done)
_ = stdin.Close()
_ = stdout.Close()
})
return &PipedProcess{
command: command,
stdin: stdin,
stdout: stdout,
parent: ctx,
cancel: cancel,
stopIO: stopIO,
ioDone: done,
}, nil
}