So I'm working on some background task and I ended up having to spawn a child processes (using a binary provided by another team). At some point I want to stop such a process if it times out.
Seems straightforward enough.
def run!(command, timeout)
Timeout.timeout(timeout) do
stdin, stdout, wait_thr = Open3.popen2e(command)
@pid = wait_thr.pid
# ... boring and irrelevant...
end
rescue Timeout::Error
Process.kill 'TERM', @pid
Process.wait pid
raise
end
Now I also quite like prepending my command with a call to time. Nice logs and all. This makes a command something like this (MacOS)
gtime -f 'Time spent %E memory used %M' some/binary --with parameters"
And so my process tree becomes something like this
ruby (my background job)
\__ gtime
\__ some/binary
Of course now when I kill the child process, only gtime is killed, the binary lives on.
- If I had control over the executable I'm using as the immediate child, I could probably handle
TERMand kill its immediate children processes. But it'stime/gtimeso I obviously don't. But maybe there's some arcane parameter? - The docs mention process groups but of course the children share the same process group as my parent process. Is there a way to spawn a process in a new process group thus making the "kill the entire process group" option viable?
I also could probably parse the ps output, build a process tree and traverse it killing processes one-by-one, but it seems a bit overkill (sorry). Is there something really basic I'm missing here?