I am trying to communicate with several child processes, each of which calls a web service and then writes a small amount of data on STDOUT. I want to read from all of them that I can, and then declare the rest timed out. The problem is that the open2 and IO::Select don't seem to be reliable.
I have trimmed the problem down to a single-child case. Sometimes I am able to read the process output, and sometimes it times out with nothing. I've even seen the child's output appear on the regular STDOUT as if it had never been redirected, while the parent process gets an empty buffer back!
Do you have any ideas about what could be going wrong, or suggestions for better ways to do this?
A code example is below.
use strict; use IPC::Open2; use IO::Select; sub sys_read { my ($fh) = @_; my $blksize = 4096; my $len; my $data = ""; my $buff; READS: while ($len = sysread($fh, $buff, $blksize)) { if (!defined $len) { next READS if $! =~ /^Interrupted/; return undef; } $data .= $buff; } return $data; } # The tester.pl script calls a web service using lines like this: #my $ua = LWP::UserAgent->new; #my $response = $ua->request(POST $uri, [ackhost => $ackhost, # data => $data, # pid => $pid]); my @command = ("/usr/bin/perl", "./tester.pl"); my($wtr, $rdr); # trying an autovivification this time. my $pid = open2($rdr, $wtr, @command); close $wtr; my @lst; push @lst, $rdr; my $timeout = 4.0; my @ready; READLOOP: while(@ready = IO::Select->new(@lst)->can_read($timeout)) { HANDLELOOP: foreach my $rh (@ready) { # This might block and sysread might be better, but let's see +.. my $buff = sys_read($rh); print "buff is *$buff*\n"; close $rh; @lst = (); } } if (scalar(@lst)) { print "Timed out with nothing this time\n"; }
In reply to open2 unreliable? by Anonymous Monk
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |