jca has asked for the wisdom of the Perl Monks concerning the following question:

Yo monks,
I'm trying to create a script which forks into multiple processes. I can't use ithreads since this needs to run on a box with only 5.6.0, and threads support not compiled in.
The problem is that I want to make sure that if I want to die in the event of an error, I need to bring down _all_ the processes rather than just the errant process. I've found much discussion of how to kill children, and process groups from the parent process, but have not been able to get this to work from a child. So, for example, here's a quick script which forks and create a child process, then calls a die from the parent process, which calls kill(9, -$$) to nuke the entire process group.
#!/usr/local/bin/perl -w use strict; $SIG{__DIE__} = sub {warn "uurk\n"; kill(9, -$$)}; if (my $pid=fork) { my $i=0; do { sleep 1; print "Parent thread ($$) - not dead yet...\n"; $i++; } until $i == 3; die; } elsif (defined $pid) { do { sleep 1; print "Child thread ($$) - not dead yet...\n"; } until 1 == 0; }
When run, this gives me...
bio-man@saturn [dbupdate] ./ugly_forker Parent thread (17387) - not dead yet... Child thread (17388) - not dead yet... Parent thread (17387) - not dead yet... Child thread (17388) - not dead yet... Parent thread (17387) - not dead yet... Child thread (17388) - not dead yet... uurk Killed bio-man@saturn [dbupdate]
lovely - just what I wanted. So what if I call die from the child....
#!/usr/local/bin/perl -w use strict; $SIG{__DIE__} = sub {warn "uurk\n"; kill(9, -$$)}; if (my $pid=fork) { do { sleep 1; print "Parent thread ($$) - not dead yet...\n"; } until 1 == 0; } elsif (defined $pid) { my $i=0; do { sleep 1; print "Child thread ($$) - not dead yet...\n"; $i++; } until $i == 3; die; }
This give me...
bio-man@saturn [dbupdate] ./ugly_forker Parent thread (19689) - not dead yet... Child thread (19690) - not dead yet... Parent thread (19689) - not dead yet... Child thread (19690) - not dead yet... Parent thread (19689) - not dead yet... Child thread (19690) - not dead yet... uurk Died at ./ugly_forker line 91. Parent thread (19689) - not dead yet... Parent thread (19689) - not dead yet... ^C bio-man@saturn [dbupdate]
Doh!...Anyone have any ideas on how to make a child take out the process group, and why this is not working?
Many thanks,
James

Replies are listed 'Best First'.
Re: parenticide...
by Abigail-II (Bishop) on Nov 27, 2002 at 12:07 UTC
    You are assuming the signal is send to the other processes in the group first, but that isn't garanteed. The signal is send to all the processes, including itself. So, it could happen that the child is getting the signal before the parent, committing suicide. End of process. No further signals send.

    There's an example in man perlipc, but it's sending the HUP signal instead. In the example, it will first set $SIG {HUP} to 'IGNORE', then send the signal.

    You should consult Stevens' Advanced Programming in the UNIX environment.

    Abigail

Re: parenticide...
by iburrell (Chaplain) on Nov 27, 2002 at 17:23 UTC
    What you can do is only have the parent take out the children. The parent process forks off the children, and then wait()'s until one of the children die's. Then it kills all of its children. One advantage is that the parent can keep track of the children pid's and doesn't need to kill the process group.

    If you need to have the parent do some processing, the parent could do the killing in a SIG{CHLD} handler. You would need to worry about race conditions since the killed children will produce CHLD signals.

    BTW, I think your code doesn't work because kill() sends the signal to process group when the signal is negative, not the process id. The documentation says that negative process numbers only work on SysV-based systems.

      Thanks for everyones input. I have managed to make it behave by using getppid in the child thread and signalling that pid - I am also using waitpid in the parent process to make sure that all the children finish doing what they are supposed to...and to try to keep a lid on the zombies...

      well he certainly looks dead...
Re: parenticide...
by Mr. Muskrat (Canon) on Nov 27, 2002 at 16:30 UTC

    Reminds me of Scene 2 from Monty Python and the Holy Grail. "Bring out your dead!"