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

I am trying to learn how to fork() standalone processes from a parent Perl script. When I execute my learning script it does fork the sub functions, but one at a time. What I am trying to learn is how do I launch all the sub functions immediately so that all the forks are running together with the parent. Here is my learning code. I have tried reading the man on fork(), but I must be dense, stupid or both, because I can't seem to figure it out.
#!/usr/bin/perl $SIG{CHLD} = "IGNORE"; $f1="file1.txt"; $f2="file2.txt"; $f3="file3.txt"; $naptime=5; sub count{ print "Starting Fork 1\n"; open(FILE1, ">$f1"); while($x < 10){ $x=$x+1; print FILE1 "$x\n"; sleep($naptime); } close(FILE1); fork && exit; } sub count2{ print "Starting Fork 2\n"; open(FILE2, ">$f2"); while($y < 10){ $y=$y+1; print FILE2 "$y\n"; sleep($naptime); } close(FILE2); fork && exit; } count(); count2(); print "Starting Parent Process\n"; open(FILE3, ">$f3"); while($z < 10){ $z=$z+1; print FILE3 "$z\n"; sleep($naptime); } close(FILE3); print "Parent Script Finished!\n"; ########################################################
Somebody please put me out of my misery!
Thanks,
Danny

update (broquaint): added <code> tags

Replies are listed 'Best First'.
Re: fork() && exit;
by stvn (Monsignor) on Feb 23, 2004 at 16:36 UTC
    Your learning script can be described as is doing this:

    In the main parent process you are running the function count(), at the end of count you fork a new process (NOTE: if the value of fork returns true then you are in the parent process, a false value indicates you are in the child process) you then have "&& exit" following your fork, this results in the parent process being exited and the child process then continues on.

    After the count() function is finished executing, your control is then in your child process, and you parent will have exited. So your child process then runs count2(). At the end of count2() you also "fork && exit" which results in the creation of a new child process and the exiting of the first child process. This new child is essentially the grandchild of the original process.

    This grandchild process then executes the code at the bottom of your script. And as there is nothing more, it exits after that.

    Seeing this visually may help explain it, so here is my (early morning/pre-coffee) attempt at it:

    -> parent executes count -> count creates child <- parent exits -> child executes count2 -> count2 creates grandchild <- child exits -> grandchild executes end of script <- grandchild exits

    My guess is this is not what you are after. The common code construct for use with fork is this:

    my $PID = fork(); if ($PID) { # in the parent process } else { # in the child process }
    I am not sure what your final intentions were in with this script, but here is a reworking of your example that will fork 3 seperate child processes from the parent and execute 3 functions then in parallel. It will also have the parent process wait for all 3 children to exit.

    -stvn
      my $PID = fork(); if ($PID) { # in the parent process } else { # in the child process }
      Bzzzt! That should read:
      my $PID = fork(); if ($PID) { # in the parent process } else { # in either the child process or the parent # process, depending on whether the fork() # succeeded or failed. }
      Always, always, always check the return values of your system calls. And that includes fork.

      Abigail

        Absolutely correct. I will now punish myself as all devout monks should do:

        Bad programmer,... sloppy code!..... sloppy code!... Bad!!

        I will now force myself to code in PHP for the next 2 weeks as further punishment for my sins.

        (I forget sometimes how dangerous simplifications are in the context of fork.)

        -stvn
      WOW! A picture is worth a thousand words. Thank you both very much. That is exactly what I was trying to understand. This helps very much. I'd buy you both a cup of Joe if ya were here. Thanks again. Danny
Re: fork() && exit;
by Abigail-II (Bishop) on Feb 23, 2004 at 16:18 UTC
    There's not much point of doing a 'fork && exit', except for detaching. 'fork && exit' means that the program forks, and if it succeeds, the parent immediately terminates. You are better off doing something like:
    my $pid1 = fork err die "fork: $!"; # Get the // patch... unless ($pid1) { # Child 1 count; exit; } my $pid2 = fork err die "fork: $!"; unless ($pid2) { # Child 2 count2; exit; } # Parent. ....

    Abigail

      This is the best I could find re: the err operator. Cool stuff though. Got any links to that path around Abigail?

      -stvn
        That's a document about perl6, which seems to be vaporware.

        Try the README and/or perldelta.pod file coming with a recent existing version of perl. I'm talking about working code, not fairy tales. ;-)

        Abigail

      Abigail,

      An initial google search and perldoc search didn't reveal anything about "fork err". Can you please provide a link to any info regarding it? TIA

      -stvn
        err is an operator (and has nothing to do with fork), which you get if you install the // patch (for 5.8.1, 5.8.2 or 5.8.3), or if you run bleadperl.

        Abigail

Re: fork() && exit;
by agentv (Friar) on Feb 23, 2004 at 21:16 UTC
    ...when I saw your initial code, I thought I could see what was going wrong, based upon my guess about your intention. And that has been well addressed.

    What also occurred to me is that there is a good reason to use the "fork && exit" approach you started with. I've seen this well used in the creation of a bare-bones web server written in Perl.

    The algorithm worked like this:

    *) Parse command-line and exit if there are errors *) Read config file and exit if there are errors *) fork && exit # so that the... Parent dies Child continues in background acting as a server

    ...to put it another way, it's a cheap approach to backgrounding a server (or daemon) process.

    I didn't get that this was something you wanted to do, but you might want to experiment with that approach to see what it does for you. Taking into account the other things that have been explained here, you might find that this adds another tool to your bag 'o tricks.

    So that you get a complete understanding of the experiment, you will want to observe the processes that get created and ask yourself a few questions.

    • What happens when the parent process exits?
    • What is the exit code of the parent process?
    • Is the child process associated with a specific terminal?
    • Where does the output from the child go? What if you don't kill the parent, where does its output go?

    Have some fun with the variations in this strategy and decide whether this will serve you in one of your future programming tasks. But mostly have fun!

    ...All the world looks like -well- all the world, when your hammer is Perl.
    ---v