Kill child processes

1,697 views
Skip to first unread message

bernhar...@gmail.com

unread,
Jul 29, 2014, 8:32:23 AM7/29/14
to golan...@googlegroups.com
Hi all,

I already asked on StackOverflow, but couldn't find a solution yet.

I'm trying to stop the process started with exec.Command("go", "run", "server.go") and all its child processes.
But when I call cmd.Process.Kill() and the go process stops, the child process (a web server in server.go) continues to run.

package main

import (
"fmt"
"os/exec"
"time"
)

func run() *exec.Cmd {
cmd := exec.Command("go", "run", "server.go")
cmd.Start()
return cmd
}

func main() {
cmd := run()
time.Sleep(time.Second * 2)
cmd.Process.Kill()
cmd.Process.Wait()
// Child process (server.go) is still running!

fmt.Scanln()
}

It looks like Process.Kill() only stops the go (run) process, but leaves its child process (web server) running.

^C kills the whole process group, including all child (and sub-child) processes. How can I do the same?

I tried cmd.Process.Signal(os.Interrupt), syscall.SIGINT, syscall.SIGQUIT and syscall.SIGKILL, none of which killed all the processes.

Thanks,
Bernhard

Chris Hines

unread,
Jul 29, 2014, 10:18:10 AM7/29/14
to golan...@googlegroups.com, bernhar...@gmail.com
The answer depends on the OS.

James Bardin

unread,
Jul 29, 2014, 10:49:38 AM7/29/14
to golan...@googlegroups.com, bernhar...@gmail.com
When you use ^C, the shell is what takes care of terminating the entire group, and Chris Hines' answer cover the other parts of your question.

As far as the SO question, the answer is a good one, don't use `go run`. It will be more predictable to build and install a package as a whole, than try to use run on separate go source files.


On Tuesday, July 29, 2014 8:32:23 AM UTC-4, bernhar...@gmail.com wrote:

Peter Waller

unread,
Jul 30, 2014, 5:30:25 AM7/30/14
to James Bardin, golang-nuts, bernhar...@gmail.com
On 29 July 2014 15:49, James Bardin <j.ba...@gmail.com> wrote:
> When you use ^C, the shell is what takes care of terminating the entire
> group, and Chris Hines' answer cover the other parts of your question.

This is an endless source of bugs when it comes to process management
and a hard lesson to learn. People generally don't realise that their
code behaves "as they expect it to" because the process group was torn
down by CTRL-C, not by their code.

Then they run it outside of a terminal context (or are signalled by a
mechanism other than pressing CTRL-C) and are left with unexplained
orphan processes which keep using resources. I've seen this come up in
numerous contexts.

For anyone wanting to appreciate how this works in detail, it is the
kernel (!) which invokes the process group kill when pressing CTRL-C.
If you want to achieve the same effect you must also use process
groups and signal the group.

Here's the code path in the kernel when you press CTRL-C:

https://github.com/torvalds/linux/blob/ac9dc67b730f3a1d10c5abbf91ed773d1e277646/drivers/tty/n_tty.c#L1127

via

https://github.com/torvalds/linux/blob/ac9dc67b730f3a1d10c5abbf91ed773d1e277646/drivers/tty/n_tty.c#L1248

via

https://github.com/torvalds/linux/blob/ac9dc67b730f3a1d10c5abbf91ed773d1e277646/drivers/tty/n_tty.c#L1287

Tamás Gulácsi

unread,
Jul 30, 2014, 6:16:05 AM7/30/14
to golan...@googlegroups.com
How to kill a process group? Noe I'm using "kill -p pid"...

Peter Waller

unread,
Jul 30, 2014, 6:55:51 AM7/30/14
to Tamás Gulácsi, golang-nuts
It depends on your exact use case and platform how you should arrange things.

If using process groups, first it is necessary to arrange your process
so that it is in a process group, which in Linux you can do in general
by invoking a program under setsid(1).

Then to signal that process group you signal the negative PID of the
process invoked under setsid, which is the process group ID. (i.e, if
it has PID 1234, "-1234" is the process group ID)

If writing go code which invokes other programs and the go program is
responsible for signalling to those processes and all of their
children, then you have to do a bit more when using os.Exec.

You can set the SysProcAttr.Setsid to True on the process and then it
will be a session leader with a new process group associated with it.
The go code can then signal the negative of the `*Command`'s PID and
that child and all sub-processes will be signalled.



On 30 July 2014 11:16, Tamás Gulácsi <tgula...@gmail.com> wrote:
> How to kill a process group? Noe I'm using "kill -p pid"...
>
> --
> You received this message because you are subscribed to the Google Groups "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Gulácsi Tamás

unread,
Jul 30, 2014, 8:08:24 AM7/30/14
to Peter Waller, golang-nuts
I see. I haven't tried signaling the negative pid from Go yet, just
called the kill executable (and taskkill on Windows).

Peter Waller

unread,
Jul 30, 2014, 8:30:06 AM7/30/14
to Gulácsi Tamás, golang-nuts
I should probably add that the scenarios I have been talking about are
all on Linux. I don't know about the situation on Windows or other
platforms.
Reply all
Reply to author
Forward
0 new messages