I've noticed that processes started with exec.Command
get interrupted even when the interrupt call has been intercepted via signal.Notify
. I've done the following example to show the issue:
package main
import (
"log"
"os"
"os/exec"
"os/signal"
"syscall"
)
func sleep() {
log.Println("Sleep start")
cmd := exec.Command("sleep", "60")
cmd.Run()
log.Println("Sleep stop")
}
func main() {
var doneChannel = make(chan bool)
go sleep()
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
signal.Notify(c, syscall.SIGTERM)
go func() {
<-c
log.Println("Receved Ctrl + C")
}()
<-doneChannel
}
If Ctrl+C is pressed while this program is running, it's going to print:
2015/10/16 10:05:50 Sleep start
^C2015/10/16 10:05:52 Receved Ctrl + C
2015/10/16 10:05:52 Sleep stop
showing that the sleep
commands gets interrupted. Ctrl+C is successfully caught though and the main program doesn't quit, it's just the sleep
commands that gets affected.
Any idea how to prevent this from happening?
The shell will signal the entire process group when you press ctrl+c
. If you signal the parent process directly, the child process won't receive the signal.
To prevent the shell from signaling the children, you need to start the command in its own process group with with the Setpgid
and Pgid
fields in syscall.SysProcAttr
before starting the processes
cmd := exec.Command("sleep", "60")
cmd.SysProcAttr = &syscall.SysProcAttr{
Setpgid: true,
}
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