diff options
author | Tony Cook <tony@develop-help.com> | 2013-10-17 15:29:58 +1100 |
---|---|---|
committer | Tony Cook <tony@develop-help.com> | 2013-10-17 15:43:09 +1100 |
commit | e9d373c4fc63458e812eaac6aef324f1b45fd607 (patch) | |
tree | 8541974202ab72f8cd6d214ae44e47cc9a1ebe8c /t/io/closepid.t | |
parent | f2a7d0fc9f4d388e4bb0628fba2476c2789721c8 (diff) | |
download | perl-e9d373c4fc63458e812eaac6aef324f1b45fd607.tar.gz |
[perl #119893] avoid waiting on pid 0
When a filehandle is cloned into a standard handle, do_openn() copies
the pid from the original handle in PL_fdpid to the standard handle
and zeroes the entry for the original handle, so when the original
handle was closed Perl_my_pclose() would call wait4pid() with a pid of 0.
With v5.19.3-614-gd4c0274 I modified wait4pid(), perl's waitpid/wait4()
wrapper, to allow a pid of zero through to the actual system call when
available.
These combined so that following v5.19.3-614-gd4c0274 in some
circumstances closing the original handle would block by calling
waitpid(0, ...) or wait4(0, ...), which waits for any child process in
the same process group to terminate.
This commit changes Perl_my_pclose() to wait for the child only when
the stored pid is positive.
Diffstat (limited to 't/io/closepid.t')
-rw-r--r-- | t/io/closepid.t | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/t/io/closepid.t b/t/io/closepid.t new file mode 100644 index 0000000000..aa937f5258 --- /dev/null +++ b/t/io/closepid.t @@ -0,0 +1,47 @@ +#!./perl + +BEGIN { + chdir 't' if -d 't'; + @INC = '../lib'; + require './test.pl'; +} + +if ($^O eq 'dos') { + skip_all("no multitasking"); +} + +plan tests => 3; +watchdog(10, $^O eq 'MSWin32' ? "alarm" : ''); + +use Config; +$| = 1; +$SIG{PIPE} = 'IGNORE'; +$SIG{HUP} = 'IGNORE' if $^O eq 'interix'; + +my $perl = which_perl(); +$perl .= qq[ "-I../lib"]; + +my $killsig = 'HUP'; +$killsig = 1 unless $Config{sig_name} =~ /\bHUP\b/; + +SKIP: +{ + skip("Not relevant to $^O", 3) + if $^O eq "MSWin32" || $^O eq "VMS"; + skip("only matters for waitpid or wait4", 3) + unless $Config{d_waitpid} || $Config{d_wait4}; + # [perl #119893] + # close on the original of a popen handle dupped to a standard handle + # would wait4pid(0, ...) + open my $savein, "<&", \*STDIN; + my $pid = open my $fh1, qq/$perl -e "sleep 50" |/; + ok($pid, "open a pipe"); + # at this point PL_fdpids[fileno($fh1)] is the pid of the new process + ok(open(STDIN, "<&=", $fh1), "dup the pipe"); + # now PL_fdpids[fileno($fh1)] is zero and PL_fdpids[0] is + # the pid of the process created above, previously this would block + # internally on waitpid(0, ...) + ok(close($fh1), "close the original"); + kill $killsig, $pid; + open STDIN, "<&", $savein; +} |