I have a piece of go code like:
func Foo() {
cmd := exec.Command("command that takes a long time")
err = cmd.Start()
if err != nil {
panic(err)
}
return
}
func main() {
Foo()
panic("program quit abruptly")
}
The sleep command will still be active even though the main process ended, is it possible to link these so the cmd
will be killed if the parent is?
CodePudding user response:
If your desire is that the process you initiated is killed when your program exits, then you can inject a context:
func Foo(ctx context.Context) {
cmd := exec.CommandContext(ctx, "command that takes a long time")
_ = cmd.Start()
return
}
func main() {
ctx, cancel := context.WithCancel(context.Background())
Foo(ctx)
defer cancel()
panic("program quit abruptly")
}
This code works by creating a context with a cancel function. This context is then sent to Foo
and from there to the command function. When cancel
is called, the context will be cancelled, causing the child process to be killed. To ensure that the context is cancelled, we defer the call to cancel
, which ensures that the context is cancelled when the program exits for any reason, including a panic.
If your desire is to cancel only on panic, you can modify main
slightly:
func main() {
ctx, cancel := context.WithCancel(context.Background())
Foo(ctx)
defer func() {
if r := recover(); r != nil {
cancel()
}
}()
panic("program quit abruptly")
}