I have a kind-of workaround. Firstly, I see that Go has the ability to
start a new session for the child with Setsid called. However on timeout I
still need to kill the process group (-pid) instead of the process, which I
can do by implementing the context deadline manually:
cmd := exec.Command("/bin/sh", "-c", "exec yes >/dev/null")
if cmd.SysProcAttr == nil {
cmd.SysProcAttr = &syscall.SysProcAttr{}
}
cmd.SysProcAttr.Setsid = true
go func() {
select {
case <-ctx.Done():
// Race by doing it here and not in os/exec; maybe
some other
// process gets the pid in the mean time
if cmd.Process.Pid > 1 && (cmd.ProcessState == nil
|| !cmd.ProcessState.Exited()) {
err := syscall.Kill(-cmd.Process.Pid,
os.Kill.(syscall.Signal))
if err != nil && err != syscall.ESRCH {
fmt.Printf("Ooops, signal failed:
%v\n", err)
}
}
}
}()
err := cmd.Run()
// rest of code the same
This appears to solve both problems: I get sensible resource accounting,
*and* the shell and its children are killed.
1 Run(): signal: killed
rusage 1: Utime={0 271899}, Stime={0 727730}, Maxrss=1892
2 Run(): signal: killed
rusage 2: Utime={0 459969}, Stime={1 539899}, Maxrss=2004
4 Run(): signal: killed
rusage 4: Utime={0 979834}, Stime={3 19489}, Maxrss=1904
Bye!
To make this work without the race, I would like to suggest that the
Process.Kill() <https://golang.org/pkg/os/#Process.Kill> function checks
the value of SysProcAttr.Setsid, and if it's true, sends the kill signal to
the process group rather than just the process. This way, the regular
exec.CommandContext would clean up properly.
(Note: I would *not* change Process.Signal(); any signal sent that way,
including the Kill signal, should just go to the single process).
This is a nominally a change in behaviour, although I can't see that the
current behaviour is actually very useful - that is, killing the parent,
but letting its children re-attach themselves to pid 1 as (in effect)
unsupervised daemons. In addition, it would only be a change in behaviour
for those people who have applied Setsid=true.
However if necessary it could be made backwards-compatible by adding a new
flag to SysProcAttr, e.g. "KillProcessGroup" which would make Process.Kill
send to -pid instead of pid.
Thoughts?
--
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 [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/golang-nuts/b471570e-8a69-44fc-8936-4698405487efo%40googlegroups.com.