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

Greetings All!

I think I have the forking business down, along with the flocking (thanks to Abigail). My new question is this: so, in the invocation of the tool mentioned here, the user usually calls many different files, in the order that they are supposed to run in. So, waiting might be in order, but the question is how? I propose this:

1)Start a child for every server that the file has to go to
2)In the initial fork, keep track of the pid's of the children (put them in an array?)
3)Have the parent do a waitpid on each of the children pid's
4)Once all the children have returned, continue on with the next file (repeat the process)

It is the waitpid that I'm a bit shaky on. The camel wasn't much help. Any light you could shine on this problem would be appreciated.

Thanks,
thor

Replies are listed 'Best First'.
Re: Fork novice requests help...Part Deux
by Abigail (Deacon) on Jun 21, 2001 at 03:51 UTC
    You want to use wait. It will return -1 if there are no more child processes.
    foreach my $file (@files) { ... forking goes here ... while (wait () != -1) { ... check $? ... } }
    See also the wait entry in perlfunc, the perlipc manual page, and the wait(2) manual page.

    -- Abigail

      Greetings all,

      I can't seem to get this thing to work! Can wait be called in such a way that the parent is made aware of the presence of children? What I want to do is something similar to this:

      foreach $letter (x','y','z'){ foreach $number (1 .. 5){ if (wait() != -1){ if ($pid = fork){ print "Forking for $letter, $number\n"; sleep 15; exit; }}}}

      I know that this doesn't work as I've written it. What I would like for the code above to do is to fork off children for 'x' at the same time, wait for all of those children to finish, and only then, start forking off children for 'y'. Is there any way to do this?

      Thanks in advance,
      thor
        I think you mean something like this:
        #!/opt/perl/bin/perl -w use strict; my %kids; foreach my $letter ('x' .. 'z') { print localtime () . ": Forking kids for $letter\n"; foreach my $number (1 .. 5) { my $code = "$letter$number"; my $pid = fork; die "Failed to fork $code" unless defined $pid; $kids {$pid} = [$code, time] if $pid; unless ($pid) { # In child. my $sleep = 2 + int rand 18; print localtime () . ": Kid $code sleeping for $sleep seconds.\n"; sleep $sleep; exit; } } while ((my $kid = wait) != -1) { print localtime () . ": Reaped kid $kids{$kid}->[0] after ", time () - $kids {$kid} -> [1], " seconds.\n"; } print localtime () . ": Done reaping kids for $letter\n"; sleep 1; } __END__
        Running this produces:
        Tue Jun 26 19:40:41 2001: Forking kids for x
        Tue Jun 26 19:40:42 2001: Kid x5 sleeping for 7 seconds.
        Tue Jun 26 19:40:42 2001: Kid x2 sleeping for 9 seconds.
        Tue Jun 26 19:40:42 2001: Kid x1 sleeping for 10 seconds.
        Tue Jun 26 19:40:42 2001: Kid x3 sleeping for 11 seconds.
        Tue Jun 26 19:40:42 2001: Kid x4 sleeping for 15 seconds.
        Tue Jun 26 19:40:49 2001: Reaped kid x5 after 7 seconds.
        Tue Jun 26 19:40:51 2001: Reaped kid x2 after 9 seconds.
        Tue Jun 26 19:40:52 2001: Reaped kid x1 after 10 seconds.
        Tue Jun 26 19:40:53 2001: Reaped kid x3 after 11 seconds.
        Tue Jun 26 19:40:57 2001: Reaped kid x4 after 15 seconds.
        Tue Jun 26 19:40:57 2001: Done reaping kids for x
        Tue Jun 26 19:40:58 2001: Forking kids for y
        Tue Jun 26 19:40:58 2001: Kid y4 sleeping for 4 seconds.
        Tue Jun 26 19:40:58 2001: Kid y3 sleeping for 4 seconds.
        Tue Jun 26 19:40:58 2001: Kid y5 sleeping for 7 seconds.
        Tue Jun 26 19:40:58 2001: Kid y2 sleeping for 8 seconds.
        Tue Jun 26 19:40:58 2001: Kid y1 sleeping for 10 seconds.
        Tue Jun 26 19:41:02 2001: Reaped kid y4 after 4 seconds.
        Tue Jun 26 19:41:02 2001: Reaped kid y3 after 4 seconds.
        Tue Jun 26 19:41:05 2001: Reaped kid y5 after 7 seconds.
        Tue Jun 26 19:41:06 2001: Reaped kid y2 after 8 seconds.
        Tue Jun 26 19:41:08 2001: Reaped kid y1 after 10 seconds.
        Tue Jun 26 19:41:08 2001: Done reaping kids for y
        Tue Jun 26 19:41:09 2001: Forking kids for z
        Tue Jun 26 19:41:09 2001: Kid z5 sleeping for 2 seconds.
        Tue Jun 26 19:41:09 2001: Kid z2 sleeping for 5 seconds.
        Tue Jun 26 19:41:09 2001: Kid z4 sleeping for 6 seconds.   
        Tue Jun 26 19:41:09 2001: Kid z1 sleeping for 11 seconds.
        Tue Jun 26 19:41:09 2001: Kid z3 sleeping for 12 seconds.
        Tue Jun 26 19:41:11 2001: Reaped kid z5 after 2 seconds.
        Tue Jun 26 19:41:14 2001: Reaped kid z2 after 5 seconds.
        Tue Jun 26 19:41:15 2001: Reaped kid z4 after 6 seconds.
        Tue Jun 26 19:41:20 2001: Reaped kid z1 after 11 seconds.
        Tue Jun 26 19:41:21 2001: Reaped kid z3 after 12 seconds.
        Tue Jun 26 19:41:21 2001: Done reaping kids for z
        

        -- Abigail

      The way that I read the entry in the camel was that was that if there is a backtick call between the fork and the wait, that some messy stuff happens internally. But, what you say above makes sense now that I read the entry in the camel more carefully. As long as there aren't any children lurking about, and they all started sucessfuly, I can assume that they all finished sucessfuly.
      Thanks
Re: Fork novice requests help...Part Deux
by enoch (Chaplain) on Jun 21, 2001 at 01:51 UTC
    What are you confused about concerning waitpid? The syntax is merely:
    if(my $pid = fork()) { #parent doParentStuff(); } elsif defined $pid { #child doChildStuff(); exit; } waitpid $pid, 0; #wait for child process to exit before going on in pa +rent doMoreParentStuff();
    Could you be more specific with your problem?

    Jeremy
      I'll try to explain myself better. What I want to do is this:

      1) foreach file that I have in the list, kick off the appropriate number of children
      2) wait for all of the children to return before I move on to the next file.

      It is the waiting for all of the children to return that is getting me. Maybe I'm just thinking to linearly about this...