forks, how do that?
apolo
created: 2006-01-01 03:41:42
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 (!($CHLD{1} = fork())) {" to "if (!$pid) {"

	print "child 1 -> $$\n";

	sleep 2; # other small thing, why this sleep don't work here and sleep the parent process?

	exit;    # but only for 2 seconds, if i have three sleep with 2 seconds 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 [id://17558|code] tags and line breaks

Re: forks, how do that?
created: 2006-01-01 06:14:08
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
Re^2: forks, how do that?
created: 2006-01-01 17:37:01
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.
Reaped: Re: forks, how do that?
created: 2006-01-01 23:11:35
This node was taken out by the NodeReaper on 2006-01-02 00-09-13
Reason: [trammell]: reap, troll

You may view the original node and the consideration vote tally.

Re: forks, how do that?
xdg
created: 2006-01-03 10:57:22

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 [doc://perlfork]. If you want to work with subprocesses on Windows, I recommend checking out [mod://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 [doc://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 [mod://Parallel::ForkManager] as a cleaner interface. There's also a tutorial on it: [id://291446]. 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 [http://creativecommons.org/licenses/publicdomain|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.

perlmonks.org content © perlmonks.org and apolo, NodeReaper, xdg, zentara

prlmnks.org © 2006 edmund von der burg (eccles & toad)

v 0.03