Skip to content

Commit d49d839

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 Perl#4106 Still needs tests.
1 parent 24a49cd commit d49d839

File tree

3 files changed

+31
-27
lines changed

3 files changed

+31
-27
lines changed

doio.c

-2
Original file line numberDiff line numberDiff line change
@@ -1089,7 +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)
10931092
/* PL_fdpid isn't used on Windows, so avoid this useless work.
10941093
* XXX Probably the same for a lot of other places. */
10951094
{
@@ -1104,7 +1103,6 @@ S_openn_cleanup(pTHX_ GV *gv, IO *io, PerlIO *fp, char *mode, const char *oname,
11041103
SvUPGRADE(sv, SVt_IV);
11051104
SvIV_set(sv, pid);
11061105
}
1107-
#endif
11081106

11091107
if (was_fdopen) {
11101108
/* need to close fp without closing underlying fd */

win32/win32.c

+31-24
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@
5151
#define PERL_NO_GET_CONTEXT
5252
#include "XSUB.h"
5353

54+
#if defined(USE_PERLIO)
55+
#include "perliol.h" /* For PerlIOUnix_refcnt */
56+
#endif
57+
5458
#include <fcntl.h>
5559
#ifndef __GNUC__
5660
/* assert.h conflicts with #define of assert in perl.h */
@@ -3622,7 +3626,7 @@ do_popen(const char *mode, const char *command, IV narg, SV **args) {
36223626

36233627
win32_close(p[child]);
36243628

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

36273631
/* set process id so that it can be returned by perl's open() */
36283632
PL_forkprocess = childpid;
@@ -3665,34 +3669,40 @@ win32_pclose(PerlIO *pf)
36653669
#ifdef USE_RTL_POPEN
36663670
return _pclose(pf);
36673671
#else
3672+
/* this should roughly match Perl_my_pclose() in util.c */
36683673
dTHX;
3669-
int childpid, status;
3670-
SV *sv;
3674+
int fd = PerlIO_fileno(pf);
36713675

3672-
sv = *av_fetch(w32_fdpid, PerlIO_fileno(pf), TRUE);
3673-
3674-
if (SvIOK(sv))
3675-
childpid = SvIVX(sv);
3676+
SV **svp = av_fetch(PL_fdpid, fd, FALSE);
3677+
int childpid;
3678+
if (svp) {
3679+
childpid = (SvTYPE(*svp) == SVt_IV) ? SvIVX(*svp) : -1;
3680+
SvREFCNT_dec(*svp);
3681+
*svp = NULL;
3682+
}
36763683
else
3677-
childpid = 0;
3684+
childpid = -1;
36783685

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

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

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

3694-
return status;
3697+
if (close_failed) {
3698+
RESTORE_ERRNO; /* error from the close */
3699+
return -1;
3700+
}
36953701

3702+
return should_wait
3703+
? (wait_result < 0 ? wait_result :
3704+
(status == 0 ? 0 : (errno = 0, status)))
3705+
: 0;
36963706
#endif /* USE_RTL_POPEN */
36973707
}
36983708

@@ -5685,7 +5695,6 @@ Perl_sys_intern_init(pTHX)
56855695
w32_perlshell_tokens = NULL;
56865696
w32_perlshell_vec = (char**)NULL;
56875697
w32_perlshell_items = 0;
5688-
w32_fdpid = newAV();
56895698
Newx(w32_children, 1, child_tab);
56905699
w32_num_children = 0;
56915700
# ifdef USE_ITHREADS
@@ -5728,7 +5737,6 @@ Perl_sys_intern_clear(pTHX)
57285737

57295738
Safefree(w32_perlshell_tokens);
57305739
Safefree(w32_perlshell_vec);
5731-
/* NOTE: w32_fdpid is freed by sv_clean_all() */
57325740
Safefree(w32_children);
57335741
if (w32_timerid) {
57345742
KillTimer(w32_message_hwnd, w32_timerid);
@@ -5767,7 +5775,6 @@ Perl_sys_intern_dup(pTHX_ struct interp_intern *src, struct interp_intern *dst)
57675775
dst->perlshell_tokens = NULL;
57685776
dst->perlshell_vec = (char**)NULL;
57695777
dst->perlshell_items = 0;
5770-
dst->fdpid = newAV();
57715778
Newxz(dst->children, 1, child_tab);
57725779
dst->pseudo_id = 0;
57735780
dst->cur_tid = 0;

win32/win32.h

-1
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)