Skip to content

Commit

Permalink
Reap child in case where exception has been thrown
Browse files Browse the repository at this point in the history
If open3 throws due to an issue such as an exec failure, the caller
cannot know the child PID to wait for. Therefore it is our
responsibility to reap it.

Also update POD, since on some platforms exec failures now ARE raised as
exceptions (since perlbug #72016).
  • Loading branch information
philipboulainsmoothwall authored and tonycoz committed Jul 29, 2013
1 parent 748cc03 commit cccbbce
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 2 deletions.
4 changes: 3 additions & 1 deletion ext/IPC-Open3/lib/IPC/Open3.pm
Expand Up @@ -57,7 +57,8 @@ as file descriptors.
open3() returns the process ID of the child process. It doesn't return on
failure: it just raises an exception matching C</^open3:/>. However,
C<exec> failures in the child (such as no such file or permission denied),
are just reported to CHLD_ERR, as it is not possible to trap them.
are just reported to CHLD_ERR under Windows and OS/2, as it is not possible
to trap them.
If the child process dies for any reason, the next write to CHLD_IN is
likely to generate a SIGPIPE in the parent, which is fatal by default.
Expand Down Expand Up @@ -297,6 +298,7 @@ sub _open3 {
if ($bytes_read) {
(my $bang, $to_read) = unpack('II', $buf);
read($stat_r, my $err = '', $to_read);
waitpid $kidpid, 0; # Reap child which should have exited
if ($err) {
utf8::decode $err if $] >= 5.008;
} else {
Expand Down
7 changes: 6 additions & 1 deletion ext/IPC-Open3/t/IPC-Open3.t
Expand Up @@ -14,10 +14,11 @@ BEGIN {
}

use strict;
use Test::More tests => 37;
use Test::More tests => 38;

use IO::Handle;
use IPC::Open3;
use POSIX ":sys_wait_h";

my $perl = $^X;

Expand Down Expand Up @@ -154,6 +155,10 @@ $TB->current_test($test);
isnt($@, '',
'open3 of a non existent program fails with an exception in the parent')
or do {waitpid $pid, 0};
SKIP: {
skip 'open3 returned, our responsibility to reap', 1 unless $@;
is(waitpid(-1, WNOHANG), -1, 'failed exec child is reaped');
}
}

$pid = eval { open3 'WRITE', '', 'ERROR', '/non/existent/program'; };
Expand Down

0 comments on commit cccbbce

Please sign in to comment.