Killing sons (Linux)

O

Ohad Lutzky

Maybe this isn't strictly a Ruby question, but I hope someone here can
help:

I have a job-management application, with a central daemon which
receives job requests. Upon receiving this request, it forks and then
runs "system" to run bash, which in turn runs the Matlab job. I use bash
for this in order to redirect the input and output from Matlab. pstree
output looks like this:

init-+-apache2---8*[apache2]
|-atd
...
|-ruby-+-4*[ruby---bash---MATLAB-+-matlab_helper]
| | `-15*[{MATLAB}]]
| `-{ruby}
...

Legend:
daemon ^ ^ daemon fork

Now, my system also allows a 'kill' command, intended to stop the job in
progress. This has been causing me a lot of trouble, and I suddenly
(after quite a while the system has been in production, how embarassing)
realized why - the PID I'm keeping is of the daemon fork. Killing it
doesn't kill all of its sons - it causes bash to get reparented to init!

Any idea of a clean, quick way to fix this?
 
O

Ohad Lutzky

Francis said:
Make your parent process the leader of its own process group with
setpgid(0,0). When you fork, add each child to the parent's process
group
with setpgid(0, getppid()). If you fork subchildren, make sure they get
added to the same process group. Now, to send a signal to the whole
group,
send it to (0 - pid), where pid is that of the parent. If you want them
all
to die without killing the leader, use a signal whose default behavior
is
terminate-process and ignore it in the parent.

Just to be sure - if I run the following Ruby code on a Linux system:

child = fork do
Process::setpgid 0,0
system 'bash -c "sleep 300"'
end
Process::kill 9, -child

Then I am guaranteed that no child bash, sleep or ruby process will
remain? It works, I just want to be sure I can count on that behaviour.
For contrast, in my original code, bash gets reparented to init:

child = fork do
system 'bash -c "sleep 300"'
end
Process::kill 9, child

And this code doesn't even work (ESRCH: No such process)

child = fork do
system 'bash -c "sleep 300"'
end
Process::kill 9, -child

Thank you for your help!
 
O

Ohad Lutzky

I've learned how to do redirection from within ruby
($stdwhatever.reopen), and switched to using exec instead of system - so
now I avoid two levels of depth. I also use setpgid and kill the whole
group for good measure.

Much thanks for your help!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top