views:

1615

answers:

4

Hey everybody,

I wrote a program that forks some processes with fork(). I want to kill all child- and the mother process if there is an error. If I use exit(EXIT_FAILURE) only the child process is killed.

I am thinking about a system("killall [program_name]") but there must be a better way...

Thank you all! Lennart

+4  A: 

Under UNIX, send SIGTERM, or SIGABRT, or SIGPIPE or sth. alike to the mother process. This signal will then be propagated to all clients automatically, if they do not explicitely block or ignore it.

Use getppid() to get the PID to send the signal to, and kill() to send the signal.

getppid() returns the process ID of the parent of the calling process.

The kill() system call can be used to send any signal to any process group or process.

Remarks: 1. Using system is evil. Use internal functions to send signals. 2. killall would be even more evil. Consider several instances of your program running at once.

ypnos
SIGTERM is the default signal sent by killall. Some other signals (like SIGABRT) can cause core files to be created when the process exits.
Lance Richardson
Thank you, I forgot about the core dump. My rational was that ABRT may be more appropriate due to it being error handling.
ypnos
+1  A: 

See http://stackoverflow.com/questions/284325/how-to-make-child-process-die-after-parent-exits

On Linux there's a prctl() call which is explicitly designed to send a signal to all of a process's children when the parent dies for whatever reason.

I need to check and can't do it where I am at the second, but I'm really not sure that ypnos' assertion about SIGPIPE, SIGTERM and SIGABRT being propagated to all children is correct.

However if you use kill(-ppid) (note the minus sign) then so long as the children are still in the parent process's process group then the kernel will deliver any signal to all of the children.

Alnitak
One easy test for my assumption: Open a terminal window and run some background processes in the shell. If you exit the shell cleanly, i.e. sending EOF (Ctrl+D), the background processes will stay. If you however close the window, they will be killed. Reason: Closing the window triggers a SIGPIPE for the shell process as it looses the virtual terminal.
ypnos
I don't believe that's a valid test. AFAIK on killing the terminal the kernel sends SIGPIPE to the whole process group. That is _not_ the same as a user sending an explicit SIGPIPE only to the parent process.
Alnitak
A: 

Consider suicidal approach - setting up an alarm() at the beginning of the process (both parent and child) with some positive number of seconds. If computation completes within that time and "there is no error", call alarm(0) to cancel the timer; otherwise the SIGALRM will kill the process (assuming you're not explicitly catching or ignoring it.)

Well, make a case against this instead of just down-voting :)

Nikolai N Fetissov
Did not downvote, but:- you gave an inferiour solution- your solution has several problems in its own- your solution would only work for a very restricted set of use-cases- your solution can be seen as bad programming style for several reasons- solutions without these flaws were already posted beforeThis may lead the leader to the assumption that your answer is wrong for this question.
ypnos
That's fair, thanks. Though I didn't say it's THE solution, just one of the options.
Nikolai N Fetissov
+1  A: 

If your mother process is not started by the command line, it may not be the process group leader, like as a deamon.

To ensure that your mother process is the process group leader, call setsid() during your process initialization.

Then in your child process, if you want to cause all the processes to exit:

pgid = getpgid();
kill(pgid, 15);

You can also do tricks, like telling all your siblings to suspend:

kill(pgid, 20);

And resume:

kill(pgid, 18);

codeDr