2 回答

TA贡献1876条经验 获得超7个赞
此代码中有许多争用条件。一般来说,如果你创建一个 goroutine,应该有某种同步 -- 如 、 、 或原子。chan
sync.Mutex
sync.WaitGroup
修复争用条件。
呼叫之前先呼叫 。代码不这样做。
StderrPipe()
Start()
等待戈鲁丁完成,然后再返回。
竞争条件可能会破坏结构...这可能意味着它泄漏了一根管道,这可以解释为什么挂起(因为管道的写入端没有关闭)。exec.Cmd
Read()
根据经验,请始终修复争用条件。将它们视为高优先级 Bug。
以下是如何在没有竞争条件的情况下编写它的草图:

TA贡献1818条经验 获得超7个赞
func runProcess(process *exec.Cmd) (stdout, stderr string, err error) {
outPipe, err := process.StdoutPipe()
if err != nil {
return "", "", err
}
// Call StderrPipe BEFORE Start().
// Easy way to do it: outside the goroutine.
errPipe, err := process.StderrPipe()
if err != nil {
return "", "", err
}
// Start process.
if err := process.Start(); err != nil {
return "", "", err
}
// Read stderr in goroutine.
var wg sync.WaitGroup
var stderrErr error
wg.Add(1)
go func() {
defer wg.Done()
data, err := ioutil.ReadAll(errPipe)
if err != nil {
stderrErr = err
} else {
stderr = string(data)
}
}()
// Read stdout in main thread.
data, stdoutErr := ioutil.ReadAll(outPipe)
// Wait until we are done reading stderr.
wg.Wait()
// Wait for process to finish.
if err := process.Wait(); err != nil {
return "", "", err
}
// Handle error from reading stdout.
if stdoutErr != nil {
return "", "", stderrErr
}
// Handle error from reading stderr.
if stderrErr != nil {
return "", "", stderrErr
}
stdout = string(data)
return stdout, stderr, nil
}
更简单的代码
所有这些都是由包自动完成的。您可以使用 任何 for 和 ,您不限于 。os/execio.WriterStdoutStderr*os.File
func runProcess(process *exec.Cmd) (stdout, stderr string, err error) {
var stdoutbuf, stderrbuf bytes.Buffer
process.Stdout = &stdoutbuf
process.Stderr = &stderrbuf
if err := process.Run(); err != nil {
return "", "", err
}
return stdoutbuf.String(), stderrbuf.String(), nil
}
- 2 回答
- 0 关注
- 113 浏览
添加回答
举报