Skip to content

Commit

Permalink
On Windows, avoid hang when closing read end of pipe.
Browse files Browse the repository at this point in the history
  • Loading branch information
nmisch committed Jul 24, 2022
1 parent 26f687e commit 8fc1419
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 0 deletions.
23 changes: 23 additions & 0 deletions lib/IPC/Run.pm
Original file line number Diff line number Diff line change
Expand Up @@ -1273,6 +1273,24 @@ sub _empty($) { !( defined $_[0] && length $_[0] ) }
sub _close {
confess 'undef' unless defined $_[0];
my $fd = $_[0] =~ /^\d+$/ ? $_[0] : fileno $_[0];
if (Win32_MODE) {

# Closing the read end of a pipe hangs if another process is in a read
# attempt on the read end's handle
# (https://github.com/Perl/perl5/issues/19963). Work around that by
# first using dup2() to replace the FD with a non-pipe FD.
#
# Since start() and other user-facing method calls _close() many FDs, we
# could optimize this by opening and closing the non-pipe FD just once
# per method call.
my $nul_fd = POSIX::open 'NUL';
croak "$!: open( NUL )" unless defined $nul_fd;
my $r = POSIX::dup2( $nul_fd, $fd );
croak "$!: dup2( $nul_fd, $fd )" unless defined $r;
$r = POSIX::close $nul_fd;
_debug "close( $fd (NUL) ) = ERROR $!"
if _debugging_details && !defined $r;
}
my $r = POSIX::close $fd;
$r = $r ? '' : " ERROR $!";
delete $fds{$fd};
Expand Down Expand Up @@ -2836,6 +2854,11 @@ sub start {
$kid->{OPS},
);
_debug "spawn() = ", $kid->{PID} if _debugging;
if ($self->{_sleep_after_win32_spawn}) {
sleep $self->{_sleep_after_win32_spawn};
_debug "after sleep $self->{_sleep_after_win32_spawn}"
if _debugging;
}
}
};
if ($@) {
Expand Down
3 changes: 3 additions & 0 deletions t/run.t
Original file line number Diff line number Diff line change
Expand Up @@ -1028,6 +1028,9 @@ $fd_map = _map_fds;
$h = start(
[ @perl, '-pe', 'BEGIN { $| = 1 } print STDERR uc($_)' ],
\$in, \$out, \$err,

# hangs w/o fix for https://github.com/toddr/IPC-Run/issues/77
_sleep_after_win32_spawn => 1,
);
isa_ok( $h, 'IPC::Run' );
is( $?, 99 );
Expand Down

0 comments on commit 8fc1419

Please sign in to comment.