grinder has asked for the wisdom of the Perl Monks concerning the following question:
Monk, I am in a maze of twisty interprocess communications, all different.
I have a process that spawns a number of kids. It reads a line from a data file, and then writes that line to each kid. A kid may choose to reply, or it may remain silent. I've been looking for the best way to handle this. I can assume that if the kid doesn't reply within one second, it's as if it never will.
I've been perusing the Cookboot, perlipc and IPC::Open2 and I can't get no satisfaction (woah-ho-ho). I hesitate to show the code I've been toying with, because it will show what an amateur I am at this. I have done quite a bit of this sort of stuff, but I've always been able to get away with the fact that the problem at hand mapped nicely to one of the examples. I think the fact that a child may remain silent is the trickiest thing (as in: non-blocking reads).
It seemed to me that the nicest solution was to use socketpair, as per perlipc. But after I started to bend the example more into the shape I wanted it to be, I think I ran into a wall of [bs]uffering.
So here's the code:
#! /usr/bin/perl use strict; use constant DUMMY => 1; use Socket; use IO::Handle; socketpair(CHILD, PARENT, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die "soc +ketpair client: $!"; CHILD->autoflush(1); PARENT->autoflush(1); if (my $kid = fork) { close PARENT; for my $key( @ARGV ) { print "parent($$) send [$key]\n"; print CHILD "$key\n"; chomp(my $line = <CHILD>); print "parent($$) recv [$line]\n"; } close CHILD; waitpid($kid,0); } else { die "cannot fork: $!" unless defined $kid; close CHILD; if( DUMMY ) { while( chomp(my $line = <PARENT>) ) { print "child($$) recv [$line]\n"; select undef, undef, undef, 0.2; if( rand() < 0.5 ) { my $now = "$line " . time; print "child($$) send [$now]\n"; print PARENT "$now\n"; } } close PARENT; } else { exec qw{ /bin/foo -c bar } or die "child could not exec: $!\n" +; } }
The above works if DUMMY is set to 1 and the kid replies each time. And if I set DUMMY to 0, in order to make the kid exec the program I really want to use it dies with a sullen Broken pipe, and I don't understand why. I know I need a select loop to see if there are handles with data waiting on them, but when I read the man page I feel like a rabbit caught in headlights.
What's more, the code above is for one kid, I need an array of them.
My dream is that I would be able to hide all this nasty stuff behind subroutines, which would in turn let me Memoize them, because it turns out that I ask the kids the same question over and over again (a bit like real life, eh?)
Thanks for any clues I can use.
update: bbfu's remark taken: this is not for Win32, so I'm not worried about Windowisms
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Non-blocking IPC to and from multiple children
by bbfu (Curate) on Mar 29, 2004 at 15:33 UTC | |
|
Re: Non-blocking IPC to and from multiple children
by Fletch (Bishop) on Mar 29, 2004 at 16:06 UTC | |
|
Re: Non-blocking IPC to and from multiple children
by zentara (Cardinal) on Mar 29, 2004 at 16:54 UTC |