http://www.perlmonks.org?node_id=74668

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

I need to write an application that forks multiple childs, maintaining for each child a communication channel, so that the childs can send data back to the parent (output and informations about their state).
Reading about interprocess communication, it seemed to me that pipes could solve my problem. Here what I naively wrote :)
#!/usr/bin/perl use strict; use FileHandle; use Data::Dumper; my $childs = { A => { pid => undef, handler => undef, blabla => () }, B => { pid => undef, handler => undef, blabla => () }, C => { pid => undef, handler => undef, blabla => () } }; foreach my $name ( keys %{$childs} ) { $childs->{ $name }->{ handler } = new FileHandle; $childs->{ $name }->{ pid } = $childs->{ $name }->{ handler }->ope +n( "-|" ); if ($childs->{ $name }->{ pid }) { # The child's talking... while(my $line = $childs->{ $name }->{ handler }->getline()) { push @{$childs->{ $name }->{ blabla }}, $line; } } else { # Childs' STDOUTs are read by the parent print "Hi! I'm $name and I'm good!"; exit; } } print Dumper( $childs );
As you can see, I maintain a hash for each child, containing a file handler that is used by the parent to read child's output. But this does not work, because the while-block that read child's output is blocking. This way doesn't seem to be worth further exploring. How could I realize what I've described at the beginning of this node?

Replies are listed 'Best First'.
Re (tilly) 1: Coping with a large family (interprocess communication)
by tilly (Archbishop) on Apr 23, 2001 at 15:03 UTC
    It sounds like you want something like IO::Select.

    Also note that you will want to properly close the filehandle when you are done, and then do a waitpid to "reap" the child, else you will get zombies. (That is the nickname for a process whose useful life is over, but it has to linger to tell its parent its return code.)

Re: Coping with a large family (interprocess communication)
by AgentM (Curate) on Apr 23, 2001 at 18:18 UTC
    Could the problem be that you don't actually fork anywhere? Essentially, the child pid code if statement is never executed. In your parent code, you should first be reading from the shared fd-which you don't do- but it's probably not best to give the same handle to every child unless the data is small. I'd also suggest skipping all of this complicated file handler stuff and sticking to the half-duplex pipe. A Filehandle to a child won't accomplish much. ++ for variable name $childs! Hilarious! Ask me further if you need any clarification. Good luck!
    AgentM Systems nor Nasca Enterprises nor Bone::Easy nor Macperl is responsible for the comments made by AgentM. Remember, you can build any logical system with NOR.
Re: Coping with a large family (interprocess communication)
by Rhandom (Curate) on Apr 23, 2001 at 18:52 UTC
    You may want to look at Re: multiple fork() where a lot of this is handled for you.

    The idealogies for it plus some extra goodies can be found in the Net::Server module on CPAN (look in the lib/Net/Server/PreFork.pm module).

    my @a=qw(random brilliant braindead); print $a[rand(@a)];