http://qs321.pair.com?node_id=493708


in reply to How to tell a child what to do?

The standard way of doing this is using pipe opens. man perlipc has some examples - the example uses communication between the parent and a single child, but filehandles can easily be saved in a datastructure.

Note that if you use pipe-open, open returns the PID of the child. To determine a child terminating, set up a signal handler to catch SIGCLD. This signal doesn't tell you the pid, but if you do a wait or a waitpid in the handler, you do. Given the PID of the terminated child, you know which task was assigned to it (assuming you stored this information when dealing out the tasks).

Study man perlipc, it's a real treasure trove. It should have enough examples to get you on your way.

Replies are listed 'Best First'.
Re^2: How to tell a child what to do?
by Eyck (Priest) on Sep 21, 2005 at 10:12 UTC
    You are surprisingly right,

    I somehow always regarded

    $pid = open(KID_TO_WRITE, "|-");
    trick as a way to talk with only one child, but if we rewrite it like this:
    $fh = new FileHandle; my $sleep_count = 0; do { $pid = open($fh, "|-"); unless (defined $pid) { warn "cannot fork: $!"; die "bailing out" if $sleep_count++ > 6; sleep 10; } } until defined $pid; my (@some_data)=qw[a be ce]; if ($pid) { print $fh @some_data; close($fh) || warn "kid exited $?"; } else { while (<STDIN>) { print "GOT: $_\n"; # child's STDIN is parent's KID } exit; # don't forget this };
    then we get to hold whole array of different $fd's, each for talking with one child. This would be clean and reliable, exactly what I wanted.

    Thanx.

      on second thought..this doesn't work that well with more then one fd open...it hangs on close($fd). Maybe there's an error in my code:
      print "I'm $$\n;"; use FileHandle; $fh = new FileHandle; $fh1 = new FileHandle; my $sleep_count = 0; do { $pid = open($fh, "|-"); unless (defined $pid) { warn "cannot fork: $!"; die "bailing out" if $sleep_count++ > 6; sleep 10; } } until defined $pid; if ($pid) { print "I'm master($$) $pid...\n"; } else { print "Waiting for commands($$)..\n"; while (<STDIN>) { print "GOT: $_\n"; # child's STDIN is parent's KID } exit; # don't forget this }; do { $pid1 = open($fh1, "|-"); unless (defined $pid1) { warn "cannot fork: $!"; die "bailing out" if $sleep_count++ > 6; sleep 10; } } until defined $pid1; if ($pid1) { print "I'm master($$) $pid1...\n"; } else { print "Waiting for commands($$)..\n"; while (<STDIN>) { print "GOT: $_\n"; # child's STDIN is parent's KID } exit; # don't forget this }; my (@some_data)=qw[a be ce]; print "($$)PID: $pid\n"; print $fh @some_data; print "($$) printing done, let's close:\n"; close($fh) || warn "kid exited $?"; print "($$)PID: $pid1\n"; print $fh1 @some_data; print "($$) printing done, let's close:\n"; close($fh1) || warn "kid exited $?"; print "END FH TEST\n\n\n";
        I wrote it slightly differently, and it seems to work for me:
        #!/usr/bin/perl use strict; use warnings; print "I'm the master ($$)\n"; my %pids; my $children = 2; for my $x (1 .. $children) { my ($fh, $pid); my $tries = 6; do {$pid = open $fh, "|-"; unless (defined $pid) { warn "fork: $!\n"; die "bailing out" unless $tries--; sleep 5; } } until defined $pid; if ($pid) { print "I'm master ($$) of child ($pid)\n"; $pids {$pid} = $fh; } else { printf "I'm a child ($$) of master (%d)\n", getppid; while (<>) { chomp; printf "Child ($$) received: [%s]\n", $_; } print "Child ($$) exiting\n"; exit; } } my $count = 0; while (my ($pid, $fh) = each %pids) { my $data = sprintf "[[%02d]]", ++$count; printf "Sending data %s to child (%d)\n", $data, $pid; print $fh $data, "\n"; } while (my ($pid, $fh) = each %pids) { printf "Closing handle to child (%d)\n", $pid; close $fh or warn "Failed to close handle for child ($pid)\n"; } print "Last line\n"; __END__ I'm the master (19054) I'm a child (19055) of master (19054) I'm master (19054) of child (19055) I'm a child (19056) of master (19054) I'm master (19054) of child (19056) Sending data [[01]] to child (19056) Sending data [[02]] to child (19055) Closing handle to child (19056) Child (19056) received: [[[01]]] Child (19056) exiting Closing handle to child (19055) Child (19055) received: [[[02]]] Child (19055) exiting Last line