The following works just fine when cmd finishes in the allotted time. However, the timeout is not working. While it does print "It's dead Jim"
, not only does it fail to print "Done waiting"
, but the process is not actually killed. It continues to run, and "Done waiting"
never prints.
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")
}()
I don't think it should make a difference, but for what it's worth the command is go test html
. The reason it's timing out is because I'm injecting an error that causes an infinite loop before running it. To add to the confusion, I tried running it with go test net
. There was a timeout, and it worked correctly.
I'm not sure when it was added, but as of Go 1.11 you can set the Pdeathsig
on a subprocess to syscall.SIGKILL
. This will kill the child when the parent exits.
cmd, _ := exec.Command("long-running command")
cmd.SysProcAttr = &syscall.SysProcAttr{
Pdeathsig: syscall.SIGKILL,
}
cmd.Start()
os.Exit(1)
The cmd
should be killed on exit.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With