I have a situation where I need to kill a process after some time. I start the process and then:
case <-time.After(timeout):
        if err := cmd.Process.Kill(); err != nil {
            return 0, fmt.Errorf("Failed to kill process: %v", err)
        }
kills the process. But it only kills the parent process not the 5-10 child processes that main process starts. I also tried creating a process group and then doing:
syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
to kill main and grandchild processes, but not working. Is there any other way I can kill the processes.
I think this is what you need:
cmd := exec.Command(command, arguments...)
// This sets up a process group which we kill later.
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
if err := cmd.Start(); err != nil {
    return err
}
// buffered chan is important so the goroutine does't
// get blocked and stick around if the function returns
// after the timeout
done := make(chan error, 1)
go func() {
    done <- cmd.Wait()
}()
select {
case err := <-done:
    // this will be nil if no error
    return err
case <-time.After(time.Second):
    // We created a process group above which we kill here.
    pgid, err := syscall.Getpgid(cmd.Process.Pid)
    if err != nil {
        return err
    }
    // note the minus sign
    if err := syscall.Kill(-pgid, 15); err != nil {
        return err
    }
    return fmt.Errorf("Timeout")
}
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