How can I kill process, which has spawned a child using system()?

I’m using Cygwin on Windows 7 (though the same problem could perhaps also apply to a native Linux environment).

A parent process – which happens to be a Ruby program, but I guess the same problem would occur, if this were a pure C application – uses system() to execute an external (possibly long-running) command.

While this external program is running, the parent process gets killed. The child process is still alive. What can I do to ensure, that the child process gets killed too?

Here a “sandbox” scenario to explain the problem: In one terminal window, I execute the following command:

ruby -e 'puts $$; system("sh")' # Could also be a C program

Clearly, this hangs forever on the sh command, after having printed the process id.

Now I try from a different terminal window

kill -INT ... 

to kill the Ruby process. Using procps or ps, I can verify that this process is still alive. Now I use

kill -TERM ....

Still, the process doesn’t get killed. Finally I do a

kill -KILL ....

and of course, this does the job. The Ruby process is killed, but the child process (‘sh’) is still alive.

I understand that this is expected behaviour, but what is an easy and reliable workaround?

I tried to establish a session and called Process.setsid before executing system, but I get the error message

`setsid’: Operation not permitted (Errno::EPERM)

Maybe setsid is not available on Cygwin, which would not surprise me, because the Windows process handling is very different.

Any other ideas, what I could try? BTW, the code is supposed to be ported to Linux eventually, so if possible, I would like to use a solution which runs under Cygwin and Linux alike.

Source: ruby

Leave a Reply