From 8d1ab7d585200fb21bd03a4d4635707c6a2002bd Mon Sep 17 00:00:00 2001 From: fatedier Date: Mon, 9 Mar 2026 01:44:54 +0800 Subject: [PATCH] test/e2e: guard Process against double-Start and Stop-before-Start Add started flag to prevent double-Start panics and allow Stop to return immediately when the process was never started. Use sync.Once for closing the done channel as defense-in-depth against double close. --- test/e2e/pkg/process/process.go | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/test/e2e/pkg/process/process.go b/test/e2e/pkg/process/process.go index ccff7ad0..dba006c1 100644 --- a/test/e2e/pkg/process/process.go +++ b/test/e2e/pkg/process/process.go @@ -3,7 +3,9 @@ package process import ( "bytes" "context" + "errors" "os/exec" + "sync" ) type Process struct { @@ -12,9 +14,11 @@ type Process struct { errorOutput *bytes.Buffer stdOutput *bytes.Buffer - done chan struct{} - waitErr error + done chan struct{} + closeOne sync.Once + waitErr error + started bool beforeStopHandler func() stopped bool } @@ -40,26 +44,35 @@ func NewWithEnvs(path string, params []string, envs []string) *Process { } func (p *Process) Start() error { + if p.started { + return errors.New("process already started") + } + p.started = true + err := p.cmd.Start() if err != nil { p.waitErr = err - close(p.done) + p.closeDone() return err } go func() { p.waitErr = p.cmd.Wait() - close(p.done) + p.closeDone() }() return nil } +func (p *Process) closeDone() { + p.closeOne.Do(func() { close(p.done) }) +} + // Done returns a channel that is closed when the process exits. func (p *Process) Done() <-chan struct{} { return p.done } func (p *Process) Stop() error { - if p.stopped { + if p.stopped || !p.started { return nil } defer func() {