Skip to content

Commit eddb2de

Browse files
committed
Win32: eliminate the sys_intern fdpid aka w32_fdpid
This duplicated the PL_fdpid already used by every other platform but didn't handle the transfer done when STD handles were reopened as pipes. Along with re-working win32_pclose() to behave much closer to Perl_my_pclose() from util.c and enabling the PID transfer done for STD handles on Win32, this fixes #4106
1 parent 6a64781 commit eddb2de

File tree

3 files changed

+29
-29
lines changed

3 files changed

+29
-29
lines changed

doio.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,9 +1089,6 @@ S_openn_cleanup(pTHX_ GV *gv, IO *io, PerlIO *fp, char *mode, const char *oname,
10891089
}
10901090
#endif
10911091

1092-
#if !defined(WIN32)
1093-
/* PL_fdpid isn't used on Windows, so avoid this useless work.
1094-
* XXX Probably the same for a lot of other places. */
10951092
{
10961093
Pid_t pid;
10971094
SV *sv;
@@ -1104,7 +1101,6 @@ S_openn_cleanup(pTHX_ GV *gv, IO *io, PerlIO *fp, char *mode, const char *oname,
11041101
SvUPGRADE(sv, SVt_IV);
11051102
SvIV_set(sv, pid);
11061103
}
1107-
#endif
11081104

11091105
if (was_fdopen) {
11101106
/* need to close fp without closing underlying fd */

win32/win32.c

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@
5151
#define PERL_NO_GET_CONTEXT
5252
#include "XSUB.h"
5353

54+
#include "perliol.h" /* For PerlIOUnix_refcnt */
55+
5456
#include <fcntl.h>
5557
#ifndef __GNUC__
5658
/* assert.h conflicts with #define of assert in perl.h */
@@ -3622,7 +3624,7 @@ do_popen(const char *mode, const char *command, IV narg, SV **args) {
36223624

36233625
win32_close(p[child]);
36243626

3625-
sv_setiv(*av_fetch(w32_fdpid, p[parent], TRUE), childpid);
3627+
sv_setiv(*av_fetch(PL_fdpid, p[parent], TRUE), childpid);
36263628

36273629
/* set process id so that it can be returned by perl's open() */
36283630
PL_forkprocess = childpid;
@@ -3665,34 +3667,40 @@ win32_pclose(PerlIO *pf)
36653667
#ifdef USE_RTL_POPEN
36663668
return _pclose(pf);
36673669
#else
3670+
/* this should roughly match Perl_my_pclose() in util.c */
36683671
dTHX;
3669-
int childpid, status;
3670-
SV *sv;
3671-
3672-
sv = *av_fetch(w32_fdpid, PerlIO_fileno(pf), TRUE);
3672+
int fd = PerlIO_fileno(pf);
36733673

3674-
if (SvIOK(sv))
3675-
childpid = SvIVX(sv);
3674+
SV **svp = av_fetch(PL_fdpid, fd, FALSE);
3675+
int childpid;
3676+
if (svp) {
3677+
childpid = (SvTYPE(*svp) == SVt_IV) ? SvIVX(*svp) : -1;
3678+
SvREFCNT_dec(*svp);
3679+
*svp = NULL;
3680+
}
36763681
else
3677-
childpid = 0;
3682+
childpid = -1;
36783683

3679-
if (!childpid) {
3680-
errno = EBADF;
3681-
return -1;
3682-
}
3684+
bool should_wait = PerlIOUnix_refcnt(fd) == 1 && childpid > 0;
36833685

3684-
#ifdef USE_PERLIO
3685-
PerlIO_close(pf);
3686-
#else
3687-
fclose(pf);
3688-
#endif
3689-
SvIVX(sv) = 0;
3686+
bool close_failed = (PerlIO_close(pf) == EOF);
36903687

3691-
if (win32_waitpid(childpid, &status, 0) == -1)
3692-
return -1;
3688+
int status;
3689+
dSAVE_ERRNO;
3690+
int wait_result;
3691+
if (should_wait) {
3692+
wait_result = win32_waitpid(childpid, &status, 0);
3693+
}
36933694

3694-
return status;
3695+
if (close_failed) {
3696+
RESTORE_ERRNO; /* error from the close */
3697+
return -1;
3698+
}
36953699

3700+
return should_wait
3701+
? (wait_result < 0 ? wait_result :
3702+
(status == 0 ? 0 : (errno = 0, status)))
3703+
: 0;
36963704
#endif /* USE_RTL_POPEN */
36973705
}
36983706

@@ -5685,7 +5693,6 @@ Perl_sys_intern_init(pTHX)
56855693
w32_perlshell_tokens = NULL;
56865694
w32_perlshell_vec = (char**)NULL;
56875695
w32_perlshell_items = 0;
5688-
w32_fdpid = newAV();
56895696
Newx(w32_children, 1, child_tab);
56905697
w32_num_children = 0;
56915698
# ifdef USE_ITHREADS
@@ -5728,7 +5735,6 @@ Perl_sys_intern_clear(pTHX)
57285735

57295736
Safefree(w32_perlshell_tokens);
57305737
Safefree(w32_perlshell_vec);
5731-
/* NOTE: w32_fdpid is freed by sv_clean_all() */
57325738
Safefree(w32_children);
57335739
if (w32_timerid) {
57345740
KillTimer(w32_message_hwnd, w32_timerid);
@@ -5767,7 +5773,6 @@ Perl_sys_intern_dup(pTHX_ struct interp_intern *src, struct interp_intern *dst)
57675773
dst->perlshell_tokens = NULL;
57685774
dst->perlshell_vec = (char**)NULL;
57695775
dst->perlshell_items = 0;
5770-
dst->fdpid = newAV();
57715776
Newxz(dst->children, 1, child_tab);
57725777
dst->pseudo_id = 0;
57735778
dst->cur_tid = 0;

win32/win32.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,6 @@ struct interp_intern {
567567
char * perlshell_tokens;
568568
char ** perlshell_vec;
569569
long perlshell_items;
570-
struct av * fdpid;
571570
child_tab * children;
572571
#ifdef USE_ITHREADS
573572
DWORD pseudo_id;

0 commit comments

Comments
 (0)