FAQ
Hi all,

I already asked on StackOverflow
<http://stackoverflow.com/questions/24982845/process-kill-on-child-processes>,
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

--
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+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Search Discussions

  • Chris Hines at Jul 29, 2014 at 2:18 pm

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

    I already asked on StackOverflow
    <http://stackoverflow.com/questions/24982845/process-kill-on-child-processes>,
    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
    The answer depends on the OS.

    For Linux, this seems to cover the bases:
    http://unix.stackexchange.com/questions/14815/process-descendants
    For Windows, look into Job Object
    http://msdn.microsoft.com/en-us/library/windows/desktop/ms684161(v=vs.85).aspx

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • James Bardin at Jul 29, 2014 at 2:49 pm
    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:

    Hi all,

    I already asked on StackOverflow
    <http://stackoverflow.com/questions/24982845/process-kill-on-child-processes>,
    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
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Peter Waller at Jul 30, 2014 at 9:30 am

    On 29 July 2014 15:49, James Bardin 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

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Tamás Gulácsi at Jul 30, 2014 at 10:16 am
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Peter Waller at Jul 30, 2014 at 10:55 am
    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 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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Gulácsi Tamás at Jul 30, 2014 at 12:08 pm
    I see. I haven't tried signaling the negative pid from Go yet, just
    called the kill executable (and taskkill on Windows).

    2014-07-30 12:54 GMT+02:00 Peter Waller <peter@scraperwiki.com>:
    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 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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Peter Waller at Jul 30, 2014 at 12:29 pm
    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.
    On 30 July 2014 13:07, Gulácsi Tamás wrote:
    I see. I haven't tried signaling the negative pid from Go yet, just
    called the kill executable (and taskkill on Windows).
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedJul 29, '14 at 1:44p
activeJul 30, '14 at 12:29p
posts8
users5
websitegolang.org

People

Translate

site design / logo © 2022 Grokbase