diff options
author | Tony Cook <tony@develop-help.com> | 2019-05-09 09:52:30 +1000 |
---|---|---|
committer | Tony Cook <tony@develop-help.com> | 2019-05-30 09:50:19 +1000 |
commit | 35608a1658fe75c79ca53d96aea6cf7cb2a98615 (patch) | |
tree | 8f6d7c8c5e5d84e252923cd66ba36825f203d5bf /doio.c | |
parent | fb5e77103dd443cc2112ba14dc665aa5ec072ce6 (diff) | |
download | perl-35608a1658fe75c79ca53d96aea6cf7cb2a98615.tar.gz |
(perl #122112) a simpler fix for pclose() aborted by a signal
This change results in a zombie child process for the lifetime of
the process, but I think that's the responsibility of the signal
handler that aborted pclose().
We could add some magic to retry (and retry and retry) waiting on
child process as we rewind (since there's no other way to remove
the zombie), but the program has chosen implicitly to abort the
wait() done by pclose() and it's best to honor that.
If we do choose to retry the wait() we might be blocking an attempt
by the process to terminate, whether by exit() or die().
If a program does need more flexible handling there's always
pipe()/fork()/exec() and/or the various event-driven frameworks on
CPAN.
Diffstat (limited to 'doio.c')
-rw-r--r-- | doio.c | 12 |
1 files changed, 11 insertions, 1 deletions
@@ -1779,7 +1779,17 @@ Perl_io_close(pTHX_ IO *io, GV *gv, bool not_implicit, bool warn_on_fail) if (IoIFP(io)) { if (IoTYPE(io) == IoTYPE_PIPE) { - const int status = PerlProc_pclose(IoIFP(io)); + PerlIO *fh = IoIFP(io); + int status; + + /* my_pclose() can propagate signals which might bypass any code + after the call here if the signal handler throws an exception. + This would leave the handle in the IO object and try to close it again + when the SV is destroyed on unwind or global destruction. + So NULL it early. + */ + IoOFP(io) = IoIFP(io) = NULL; + status = PerlProc_pclose(fh); if (not_implicit) { STATUS_NATIVE_CHILD_SET(status); retval = (STATUS_UNIX == 0); |