Acme-Sort-Sleep
view release on metacpan or search on metacpan
local/lib/perl5/IO/Async/ChildManager.pm view on Meta::CPAN
}
}
elsif( !defined $dollarat ) {
if( length( $$buffref ) >= $length_dollarat ) {
$dollarat = substr( $$buffref, 0, $length_dollarat, "" );
return 1;
}
}
if( $eof ) {
$dollarbang = 0 if !defined $dollarbang;
if( !defined $length_dollarat ) {
$length_dollarat = 0;
$dollarat = "";
}
$pipeclosed = 1;
if( defined $exitcode ) {
local $! = $dollarbang;
$on_exit->( $kid, $exitcode, $!, $dollarat );
}
}
return 0;
}
) );
$loop->watch_child( $kid => sub {
( my $kid, $exitcode ) = @_;
if( $pipeclosed ) {
local $! = $dollarbang;
$on_exit->( $kid, $exitcode, $!, $dollarat );
}
} );
return $kid;
}
sub _spawn_in_child
{
my $self = shift;
my ( $writepipe, $code, $setup ) = @_;
my $exitvalue = eval {
# Map of which handles will be in use by the end
my %fd_in_use = ( 0 => 1, 1 => 1, 2 => 1 ); # Keep STDIN, STDOUT, STDERR
# Count of how many times we'll need to use the current handles.
my %fds_refcount = %fd_in_use;
# To dup2() without clashes we might need to temporarily move some handles
my %dup_from;
my $max_fd = 0;
my $writepipe_clashes = 0;
if( @$setup ) {
# The writepipe might be in the way of a setup filedescriptor. If it
# is we'll have to dup2 it out of the way then close the original.
foreach my $i ( 0 .. $#$setup/2 ) {
my ( $key, $value ) = @$setup[$i*2, $i*2 + 1];
$key =~ m/^fd(\d+)$/ or next;
my $fd = $1;
$max_fd = $fd if $fd > $max_fd;
$writepipe_clashes = 1 if $fd == fileno $writepipe;
my ( $operation, @params ) = @$value;
$operation eq "close" and do {
delete $fd_in_use{$fd};
delete $fds_refcount{$fd};
};
$operation eq "dup" and do {
$fd_in_use{$fd} = 1;
my $fileno = fileno $params[0];
# Keep a count of how many times it will be dup'ed from so we
# can close it once we've finished
$fds_refcount{$fileno}++;
$dup_from{$fileno} = $fileno;
};
$operation eq "keep" and do {
$fds_refcount{$fd} = 1;
};
}
}
foreach ( IO::Async::OS->potentially_open_fds ) {
next if $fds_refcount{$_};
next if $_ == fileno $writepipe;
POSIX::close( $_ );
}
if( @$setup ) {
if( $writepipe_clashes ) {
$max_fd++;
dup2( fileno $writepipe, $max_fd ) or die "Cannot dup2(writepipe to $max_fd) - $!\n";
undef $writepipe;
open( $writepipe, ">&=$max_fd" ) or die "Cannot fdopen($max_fd) as writepipe - $!\n";
}
foreach my $i ( 0 .. $#$setup/2 ) {
my ( $key, $value ) = @$setup[$i*2, $i*2 + 1];
if( $key =~ m/^fd(\d+)$/ ) {
my $fd = $1;
my( $operation, @params ) = @$value;
$operation eq "dup" and do {
my $from = fileno $params[0];
if( $from != $fd ) {
if( exists $dup_from{$fd} ) {
defined( $dup_from{$fd} = dup( $fd ) ) or die "Cannot dup($fd) - $!";
( run in 0.761 second using v1.01-cache-2.11-cpan-39bf76dae61 )