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

Hey, I have a basic question on perl Fork. Once I start child process, I need the parent process to perform some action till the child process ends. I have tried using "until(waitpid)" but that doesnt work. Could someone help me out. Thanks! Here is the code..

FORK: { if ($pid=fork) { ## parent process,no operation is performed here next; } elsif (defined $pid) { ## Starting Fork, transfering data &download_a_file(); exit 0; } } until (waitpid ($pid,0) ) { ## I need to perform some action only when child process is running &calculate_network_bandwidth(); }

Replies are listed 'Best First'.
Re: Perl Forking : perform some action until child process dies
by kennethk (Abbot) on Sep 01, 2010 at 14:26 UTC
    The issue you are encountering is that waitpid ($pid,0) is a blocking call. This means that the conditional on your until loop doesn't finish executing until your child has actually returned. You can perform a non-blocking call on systems that support it using:
    use POSIX ":sys_wait_h"; #... do { $kid = waitpid(-1, WNOHANG); } while $kid > 0;
    where the above is copied from waitpid. Note that not all systems support non-blocking calls to waitpid. See also perlipc.

      Many thanx... this worked

      But I used "while $kid = = 0; " instead.. which means.. while the child process is still running.. keep calculating the bandwidth in the do { }

Re: Perl Forking : perform some action until child process dies
by locked_user sundialsvc4 (Abbot) on Sep 01, 2010 at 16:19 UTC

    In my experience, it is better for the parent process to be, basically, a supervisor, not “an active player in the game.”

    In other words, in your scenario I would have two child processes:   the one that you describe, and a second one to “perform some action.”   The parent, then, sits in a wait-state, biding its time until one of the two of them finishes their task.   The child processes, having signaled their parent, then enter a wait-state asking for further instructions.   (Queues are a great way to handle this sort of thing.)

    If the “perform some action” action needs to be suspended when the first process has completed its work, then of course the parent could signal that child to do so.   But it may well be that the work of the second process could continue, perhaps at a much lower execution priority.   The operating system could be relied-upon to fairly distribute the available CPU(s) time among the three of them, giving you a very flexible and robust arrangement.

    It is also frequently useful to devise a queue-based mechanism (hint:   there are many CPAN modules already out there for this...) which would allow you to express things like “download a file” as “create a ‘download a file’ request and place it on such-and-such a queue.”   This queue is then serviced by a pool of n “worker bee” processes or threads, all under the supervision of a parent.   The workload-level that the CPU(s) undertake is strictly governed by the size of that worker-bee pool.   (The queue, on the other hand, can become as large as it likes... or not... your option.)

    Again:   “do not do a thing already done!”   This is “a legendary architecture,” and there is plenty of well-rounded CPAN support for it.

Re: Perl Forking : perform some action until child process dies
by mr_mischief (Monsignor) on Sep 01, 2010 at 14:26 UTC

    Do you know what that next; is doing? Nothing. It's exiting a block you'd be exiting anyway.

    As for the loop waiting for waitpid to return something other than 0, my first guess is, since "doesn't work" is kind of vague, that it seems to you the loop never runs?

    Update:Yeah, what kennethk said abut it being a blocking call. I didn't even think of that for some reason. I'm going to blame lack of sleep. That explains the same loop-never-seems-to-run behavior but for the correct reason. I'll put my bad guess in a readmore. That's easier to read than a strikethrough.

    If you're having some other version of "doesn't work", then more detail may be helpful.

Re: Perl Forking : perform some action until child process dies
by rmflow (Beadle) on Sep 02, 2010 at 14:02 UTC
    maybe you should look into threads?
    use threads; my $thr = async{ &download_a_file(); }; &calculate_network_bandwidth() while($thr->is_running()); $thr->join();
    but you might need use threads::shared if there are any shared variables.
Re: Perl Forking : perform some action until child process dies
by perl-diddler (Chaplain) on Sep 02, 2010 at 22:01 UTC

    When I first looked at your question, I couldn't see the problem, you wanted to start something then wait "until" it was done (waitpid). Ok, er, oh...you want to some code to execute while you are in the wait call?

    Er, um you'll need to have someone else do that cuz, you just told it to wait until it's done.

    (or, like others have said, 1) waitpid is 'blocking' ....(that's what you wanted? No? Ooops...), so either use non-blocking form of waitpid OR have something else (process/thread) do the calculate loop. Depends on what the calc routine does and how it interacts with the existing program variables as to whether or not threads or a process would be better.

    If you use the non-waiting form of 'waitpid', be sure to read the 'perlipc' manpage to get the right example to guard against "gotcha's", like signals dropping between the cracks.

    Basically you have to use 'waitpid' IN a child process you setup before you fork. Examples are in the manpage.