On 3/30/06, Kripa Sundar <[EMAIL PROTECTED]> wrote:
> Hello all,
>
> I thought this was fairly simple (and it probably is). But I am not
> able to figure out how I can fork() off, say, five child processes, and
> wait for all of them to terminate.
1 until -1 == wait();
You'll need something more complex if you want to track the children's
exit statuses (very useful for debugging).
> Is the code below on the right track? Is it as simple as
> "wait for [EMAIL PROTECTED]"? I think this will let me wait N times,
> where N is the number of children launched. Am I right? TIA.
> Is there a simpler "wait-for-all-descendants" primitive?
What if some child has children who do not get properly cleaned up?
Those grandkids are now your responsibility.
> If some of my children are hanging, can I detect that,
> and take action to terminate them?
If you
use POSIX ":sys_wait_h";
then on most modern systems you can
$kid = waitpid(-1, WNOHANG);
to poll to see if a kid needs to be reaped. If you keep track of
which kids you launched when and which ones you've reaped, you can
decide when you think that the child needs to be terminated, and then
use the built-in kill function to send a signal to that child. (The
right signal will kill it, with or without giving it a chance to do
cleanup.)
> > my @children; # Keep track of my children's PID's.
When I've needed to do this kind of logic, I find that hashes work
better. Easier to insert/delete as I launch/reap.
> > for (1..5) {
> > my $pid = fork;
> > if ($pid) {
> > # I am in the parent.
> > push @children, $pid;
> > } elsif (defined $pid) {
> > &do_some_child_stuff($_);
Rather than worry about whether you are a child/parent for the rest of
your code, I usually put an exit() here. But note that you may need
to worry about child/parent stuff in END blocks because Perl 5.8
causes END blocks to run on exits. If you dislike that rule, then
POSIX::exit still does the old behaviour.
> > } else {
> > warn "Warning: fork() #$_ failed";
> > }
> > } # for (1..5)
> >
> > if (@children) {
> > # I am in the parent.
> > if ($wait_order eq 'FIFO') {
> > waitpid $_ for @children;
> > print "I waited for my children in FIFO order.\n";
> > } else {
> > wait for [EMAIL PROTECTED];
> > print "I waited for my children without imposing an order.\n";
> > }
> > &do_some_adult_stuff;
> > } # if (@children)
Random tips about this stuff.
Explicitly managing children and forking tends to be a lot of work.
Unless you really need the complexity, I find that it tends to be
easier to take the "poor man's" approach and do system calls and open
up pipes.
Also note that a very common source of problems is having open sockets
across a fork. For instance if you have a database connection, you
may have race conditions between what happens when the parent is
talking to the database and what happens when the child is shutting
down. Keep your eyes out for that because such races happen easily
and can be hard to diagnose.
Cheers,
Ben
_______________________________________________
Boston-pm mailing list
[email protected]
http://mail.pm.org/mailman/listinfo/boston-pm