Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Fork() Function

by carlriz (Beadle)
on May 13, 2014 at 13:32 UTC ( [id://1085899]=perlquestion: print w/replies, xml ) Need Help??

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

Quick question here. Say I fork() a process multiple times at the same point in a script. I have one variable in the script that keeps track of the child pid. Will that variable maintain each unique pid for each new process created?

Replies are listed 'Best First'.
Re: Fork() Function
by zentara (Archbishop) on May 13, 2014 at 14:50 UTC
    In addition to the good advice given above, I would like to point out 1 little pitfall which you may encounter. When forking you often get the pid of the shell process invoked which then actually spawns another pid to run your program. So be aware that the pid reported back by fork, will probably be a shell's pid. The shell then has a child, which is your actual program. See Proc://KillFam for a way to kill the entire process tree which results from your fork.

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh

      Heh ... “a little battle-won insight” that is well deserving of the many up-votes that it is now happily accumulating!   :-D   Too-bad I could only praise it once.

Re: Fork() Function
by McA (Priest) on May 13, 2014 at 13:51 UTC

    Hi,

    the following code is directly taken from the perldoc perlipc which should give an idea about the bookkeeping:

    use POSIX ":sys_wait_h"; # for nonblocking read my %children; $SIG{CHLD} = sub { # don't change $! and $? outside handler local ($!, $?); my $pid = waitpid(-1, WNOHANG); return if $pid == -1; return unless defined $children{$pid}; delete $children{$pid}; cleanup_child($pid, $?); }; while (1) { my $pid = fork(); die "cannot fork" unless defined $pid; if ($pid == 0) { # ... exit 0; } else { $children{$pid}=1; # ... system($command); # ... } }

    UPDATE: In my opinion it's essential to understand that fork does a 1-to-1-process copy. After that fork you have two processes with the same "Perl source code", just continuing to run at different positions in the code. (The if ($pid == 0) {).

    That does also mean that there is a %children hash in the child process even when only meaningfully used by the parent for child bookkeeping. But, e.g. in the currently spawned child you could ask the child's copy of %children which other child processes were spawned and not reaped just until its own birth. A kind of "I do have the following older siblings".

    Regards
    McA

Re: Fork() Function
by MidLifeXis (Monsignor) on May 13, 2014 at 13:38 UTC

    It depends what exactly you mean. Could you show some code to illustrate? (include <code>...</code> tags, etc)

    I could restate your question this way: Say I run a calculation multiple times at the same point in a script. I have one variable in the script that keeps track of the results. Will that variable maintain each unique result? I would guess not from your description, but would want to see your code before saying that as an absolute.

    --MidLifeXis

      $recorderID = fork(); if ( $recorderID == 0) { system($data); exit(0); } else if ( $recorderID > 0) { print " Start Record now ID:$recorderID\n"; $recorderID0 = $recorderID + 2 ; print "$recorderID0 \n"; $recorderFlag = 1; printlog("DebugLog: Start Record now ID in id 3:$recorderID; $r +ecorderID0"); } else { printlog("DebugLog: Con't fork child process.") }; }

      $recorderID is a global variable

        The documentation for forkperlipc, as pointed out by McA below, has an example of using a hash to store all of the PIDs that have been stared. You may want to study that example.

        So, you can think of it this way. A global scalar variable in the parent is like a bucket that can only hold one thing. Every time that you assign to that variable, perl dumps what is currently in the bucket, and puts the new thing into the bucket. Therefore, only the last child PID will be available to your parent process, at least in the way you currently have it implemented.

        A hash is like a pegboard, where you can hang many things off from the single hash variable. It differs from the bucket analogy above by storing the pegboard in the variable instead of storing a thing in the variable.

        note: not happy with the analogy - best available between my ears at the moment.

        --MidLifeXis

        Keep in mind that perl fork does not return -1, it returns undef on failure. In your code, fork failure results in system() and exit() on the parent side. A useful idiom with fork is my $pid = fork() // die; you may want if (!defined $pid) {} else if ($pid) {} else {}.

        Keep in mind that a call to system results in another fork and wait, hence your work runs in a child of a child. You may have intended a direct exec instead of system.

        Your OP question is somewhat ambiguous. Just in case, I'll mention that there is no guarantee that a newly spawned child has a different pid from some earlier (already reaped) process. Pid numbers are recycled.

        yes, but this doesn't fork "multiple times"...

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1085899]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others contemplating the Monastery: (2)
As of 2024-04-20 06:24 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found