当 cmd 在指定的时间内完成时,以下工作正常。但是,超时不起作用。虽然它确实打印了 "It's dead Jim"
,但它不仅没有打印 "Done waiting"
,而且进程实际上并没有被终止。它继续运行,并且 “Done waiting”
永远不会打印出来。
func() {
var output bytes.Buffer
cmd := exec.Command("Command", args...)
cmd.Dir = filepath.Dir(srcFile)
cmd.Stdout, cmd.Stderr = &output, &output
if err := cmd.Start(); err != nil {
return err
}
defer time.AfterFunc(time.Second*2, func() {
fmt.Printf("Nobody got time fo that\n")
if err := cmd.Process.Signal(syscall.SIGKILL); err != nil {
fmt.Printf("Error:%s\n", err)
}
fmt.Printf("It's dead Jim\n")
}).Stop()
err := cmd.Wait()
fmt.Printf("Done waiting\n")
}()
我不认为它应该有什么不同,但它的值(value)在于命令是 go test html
。它超时的原因是因为我在运行它之前注入(inject)了一个导致无限循环的错误。为了增加困惑,我尝试使用 go test net
运行它。有一个超时,它工作正常。
最佳答案
看起来问题在于 cmd.Process.Kill() 不会终止子进程。看到这个类似的问题Process.Kill() on child processes
我在这个线程中找到了解决方案 https://groups.google.com/forum/#!topic/golang-nuts/XoQ3RhFBJl8
cmd := exec.Command( some_command )
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
cmd.Start()
pgid, err := syscall.Getpgid(cmd.Process.Pid)
if err == nil {
syscall.Kill(-pgid, 15) // note the minus sign
}
cmd.Wait()
作为一个警告,这几乎肯定不能跨平台工作——我目前在 OSX Yosemite 上,我敢打赌它也能在大多数 Linux 上工作,但我还不够了解关于 BSD 有意见,我怀疑它是否适用于 Windows。
关于go - 为什么 Go 不能正确地杀死一个子进程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22470193/