I don't know anything about signals, and only a little about pipes.
From the comments on zdim's answer here it seems that signals may interfere with pipe communication between parent and child processes.
I was told that, if you're using
IO::Select
and
sysread
,
then the exit of a child process
could somehow mess up the behavior of IO::Select::can_read
,
especially if there are multiple child processes.
Please describe how to account for signals when using pipes? The below code is an example where signals are not accounted for.
use warnings;
use strict;
use feature 'say';
use Time::HiRes qw(sleep);
use IO::Select;
my $sel = IO::Select->new;
pipe my $rd, my $wr;
$sel->add($rd);
my $pid = fork // die "Can't fork: $!"; #/
if ( $pid == 0 ) { # Child code
close $rd;
$wr->autoflush;
for ( 1..4 ) {
sleep 1;
say "\tsending data";
say $wr 'a' x ( 120 * 1024 );
}
say "\tClosing writer and exiting";
close $wr;
exit;
}
# Parent code
close $wr;
say "Forked and will read from $pid";
my @recd;
READ:
while ( 1 ) {
if ( my @ready = $sel->can_read(0) ) { # beware of signals
foreach my $handle (@ready) {
my $buff;
my $rv = sysread $handle, $buff, ( 64 * 1024 );
warn "Error reading: $!" if not defined $rv;
if ( defined $buff and $rv != 0 ) {
say "Got ", length $buff, " characters";
push @recd, length $buff;
}
last READ if $rv == 0;
}
}
else {
say "Doing else ... ";
sleep 0.5;
}
}
close $rd;
my $gone = waitpid $pid, 0;
say "Reaped pid $gone";
say "Have data: @recd"