summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Boulain <philip.boulain@smoothwall.net>2012-09-03 15:16:26 +0100
committerTony Cook <tony@develop-help.com>2013-07-29 16:24:40 +1000
commitcccbbce940ea952c4c236049e98d21a011475cb1 (patch)
tree072f77b804ddc06655305a7014734e4c8cff54cf
parent748cc03cd5ccfe4fb015da434bcb7dfb6125253b (diff)
downloadperl-cccbbce940ea952c4c236049e98d21a011475cb1.tar.gz
Reap child in case where exception has been thrown
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).
-rw-r--r--ext/IPC-Open3/lib/IPC/Open3.pm4
-rw-r--r--ext/IPC-Open3/t/IPC-Open3.t7
2 files changed, 9 insertions, 2 deletions
diff --git a/ext/IPC-Open3/lib/IPC/Open3.pm b/ext/IPC-Open3/lib/IPC/Open3.pm
index 989c2f65a9..f50146f8fa 100644
--- a/ext/IPC-Open3/lib/IPC/Open3.pm
+++ b/ext/IPC-Open3/lib/IPC/Open3.pm
@@ -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.
@@ -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 {
diff --git a/ext/IPC-Open3/t/IPC-Open3.t b/ext/IPC-Open3/t/IPC-Open3.t
index 7b85b825e2..6ab519d002 100644
--- a/ext/IPC-Open3/t/IPC-Open3.t
+++ b/ext/IPC-Open3/t/IPC-Open3.t
@@ -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;
@@ -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'; };