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

I try to make a script that run three child process an return some information, when all child process finish, i need to continue with a parent process, with the information returned by the childrens, but i have soooo manyyy problems becouse i can't understand on my mind, how works the fork function, perhaps somebody help me with that, anyway, i developed this script on windows but i'm use or i hope use on linux.

when i test the script, return this:

Child 1 -> -3334

Child 2 -> -4564

parent process

Child 3 -> -4365



yes, on windows return negative process id.

On windows at least the signal CHLD or CLD not work, (but both are defined in %SIG hash),

i say that, becouse, if i do something like SIG{CHLD} = sub { print "it's work"; }; nothing happen, it's correct? why?, in fact if i use something like:

sub REAPER { # don't work almost on windows while (($child = waitpid(-1,WNOHANG)) > 0) {} $SIG{CHLD} = \&REAPER; } $SIG{CHLD} = \&REAPER;


the result of the script it's the same, why?, what wrong i do? to replace this i put three waitpit but nothing change, what can i do?

To set the priority i tried to use setpriotity, but it's not implement on windows yet,

on linux, work?

one interesting thing, if i use three wait; the script work fine, but i try to do the right,

i don't know why work with that and don't work with the other.

well nothing more for now

thank you

use POSIX ":sys_wait_h"; $|=1; #$pid=fork(); # when i use setpriority i call a fork here and replace +below in the if sentence. #$pid1=fork(); #$pid2=fork(); #setpriority($$,0); # not implement on windows :-( #setpriority($pid,1); #setpriority($pid1,2); #setpriority($pid2,3); my %CHILD = (); sub REAPER { # don't work almost on windows while (($child = waitpid(-1,WNOHANG)) > 0) {} $SIG{CHLD} = \&REAPER; } $SIG{CHLD} = \&REAPER; # if i do something like $SIG{CHLD} = sub { print "it's work"; }; # well ... nothing happen, why? if (!($CHLD{1} = fork())) { # when use setpriority i replace "if (!($C +HLD{1} = fork())) {" to "if (!$pid) {" print "child 1 -> $$\n"; sleep 2; # other small thing, why this sleep don't work here and s +leep the parent process? exit; # but only for 2 seconds, if i have three sleep with 2 se +conds 2*3 = 6 seconds, # itn't it? yeah yeah i'm lost ;-( } if (!($CHLD{2} = fork())) { print "child 2 -> $$\n"; sleep 2; exit; } if (!($CHLD{3} = fork())) { print "child 3 -> $$\n"; sleep 2; exit; } # if i replace $CHILD{1} with -1... dosen't work :-( # obviusly, when i use this i don't use the signal $SIG{CHLD} # if i only put one waitpid... well don't work #waitpid $CHILD{1}, WNOHANG; # if i put wait; the script work fine #waitpid $CHILD{2}, WNOHANG; # wait; #waitpid $CHILD{3}, WNOHANG; # wait; print "parent process\n";

Edited by planetscape - added code tags and line breaks

Replies are listed 'Best First'.
Re: forks, how do that?
by zentara (Cardinal) on Jan 01, 2006 at 11:14 UTC
    While this dosn't actually answer your question about juggling forks, I will say that this is the perfect place to use threads. Whenever you want to return data from a process, a thread makes life easier. You didn't say or show how you were going to return values....I assume through external files? Anyways, here is a simple example using threads. It is simplified purposely for the example, in a real script, you probably would put everything into a hash.
    #!/usr/bin/perl use warnings; use strict; use threads; my $thr1 = threads->new(\&sub1); my $thr2 = threads->new(\&sub2); my $thr3 = threads->new(\&sub3); my $ReturnData1 = $thr1->join; print "Thread1 returned @$ReturnData1\n"; my $ReturnData2 = $thr2->join; print "Thread2 returned @$ReturnData2\n"; my $ReturnData3 = $thr3->join; print "Thread3 returned @$ReturnData3\n"; print "Press any key to exit\n"; <>; ############################################## sub sub1 { my @values = ('Fifty-six','foo', 1); sleep 1; return \@values; } ############################################## sub sub2 { my @values = ('Forty-two','bar', 2); sleep 2; return \@values; } ########################################## sub sub3 { my @values = ('Sixty-six','baz', 3); sleep 3; return \@values; } # join() does three things: it waits for a thread to exit, # cleans up after it, and returns any data the thread may # have produced.

    I'm not really a human, but I play one on earth. flash japh
      Ok, i try to get three page with lwp, in the "same" moment, i only think in fork function but you have reason, i don't know how to work theads but i'm test an tell you, anyway, if anyone know something about the forks problem, please tell me.

      Well, thank you.
Re: forks, how do that?
by xdg (Monsignor) on Jan 03, 2006 at 15:57 UTC

    You've got several issues going on. First, if you're using fork on Windows, you're really using Perl threads behind the scenes. See perlfork. If you want to work with subprocesses on Windows, I recommend checking out Win32::Job. As mentined above, getting data back from a fork is harder than getting it back from a thread -- you probably need to use some sort of external file or pipe. See perlipc. If you're trying to do multiple child processes at the same time, you've got added complexity in handling returned data.

    For managing multiple, forked processes in general, I've seen many recommendations for Parallel::ForkManager as a cleaner interface. There's also a tutorial on it: Introduction to Parallel::ForkManager. It looks like what you want can be boiled down to something like this (adapted from the docs for it):

    use Parallel::ForkManager; $pm = new Parallel::ForkManager($MAX_PROCESSES); my @task_details = ( # data needed for each sub-process ); foreach my $task (@task_details) { $pm->start and next; # do the fork # do the sub process work using whatever details are in $task # write the results to a file somewhere, perhaps with a # pre-set name passed in $task $pm->finish; # do the exit in the child process } $pm->wait_all_children; # Continue in parent and read in the results

    -xdg

    Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.