make PerlIO handle FD_CLOEXEC
authorZefram <zefram@fysh.org>
Fri, 22 Dec 2017 15:20:26 +0000 (15:20 +0000)
committerZefram <zefram@fysh.org>
Fri, 22 Dec 2017 16:34:17 +0000 (16:34 +0000)
Move handling of close-on-exec flag for PerlIO handles into PerlIO itself.
Where PerlIO opens new file descriptors, have them opened in O_CLOEXEC
mode where possible.

doio.c
embed.fnc
embed.h
perl.c
perlio.c
pod/perliol.pod
pp_sys.c
proto.h
toke.c
util.c

diff --git a/doio.c b/doio.c
index d18e335..4b8923f 100644 (file)
--- a/doio.c
+++ b/doio.c
@@ -78,6 +78,14 @@ Perl_setfd_inhexec(int fd)
 #endif
 }
 
+void
+Perl_setfd_cloexec_for_nonsysfd(pTHX_ int fd)
+{
+    assert(fd >= 0);
+    if(fd > PL_maxsysfd)
+       setfd_cloexec(fd);
+}
+
 void
 Perl_setfd_inhexec_for_sysfd(pTHX_ int fd)
 {
@@ -85,6 +93,16 @@ Perl_setfd_inhexec_for_sysfd(pTHX_ int fd)
     if(fd <= PL_maxsysfd)
        setfd_inhexec(fd);
 }
+void
+Perl_setfd_cloexec_or_inhexec_by_sysfdness(pTHX_ int fd)
+{
+    assert(fd >= 0);
+    if(fd <= PL_maxsysfd)
+       setfd_inhexec(fd);
+    else
+       setfd_cloexec(fd);
+}
+
 
 #define DO_GENOPEN_THEN_CLOEXEC(GENOPEN_NORMAL, GENSETFD_CLOEXEC) \
        do { \
@@ -700,7 +718,7 @@ Perl_do_open6(pTHX_ GV *gv, const char *oname, STRLEN len,
                    }
                    else {
                        if (dodup)
-                            wanted_fd = PerlLIO_dup(wanted_fd);
+                            wanted_fd = PerlLIO_dup_cloexec(wanted_fd);
                        else
                            was_fdopen = TRUE;
                         if (!(fp = PerlIO_openn(aTHX_ type,mode,wanted_fd,0,0,NULL,num_svs,svp))) {
@@ -991,33 +1009,15 @@ S_openn_cleanup(pTHX_ GV *gv, IO *io, PerlIO *fp, char *mode, const char *oname,
            if (was_fdopen) {
                 /* need to close fp without closing underlying fd */
                 int ofd = PerlIO_fileno(fp);
-                int dupfd = ofd >= 0 ? PerlLIO_dup(ofd) : -1;
-#if defined(HAS_FCNTL) && defined(F_SETFD)
-               /* Assume if we have F_SETFD we have F_GETFD. */
-                /* Get a copy of all the fd flags. */
-                int fd_flags = ofd >= 0 ? fcntl(ofd, F_GETFD) : -1;
-                if (fd_flags < 0) {
-                    if (dupfd >= 0)
-                        PerlLIO_close(dupfd);
-                    goto say_false;
-                }
-#endif
+                int dupfd = ofd >= 0 ? PerlLIO_dup_cloexec(ofd) : -1;
                 if (ofd < 0 || dupfd < 0) {
                     if (dupfd >= 0)
                         PerlLIO_close(dupfd);
                     goto say_false;
                 }
                 PerlIO_close(fp);
-                PerlLIO_dup2(dupfd, ofd);
-#if defined(HAS_FCNTL) && defined(F_SETFD)
-               /* The dup trick has lost close-on-exec on ofd,
-                 * and possibly any other flags, so restore them. */
-               if (fcntl(ofd,F_SETFD, fd_flags) < 0) {
-                    if (dupfd >= 0)
-                        PerlLIO_close(dupfd);
-                    goto say_false;
-                }
-#endif
+                PerlLIO_dup2_cloexec(dupfd, ofd);
+                setfd_inhexec_for_sysfd(ofd);
                 PerlLIO_close(dupfd);
            }
             else
@@ -1027,10 +1027,6 @@ S_openn_cleanup(pTHX_ GV *gv, IO *io, PerlIO *fp, char *mode, const char *oname,
        PerlIO_clearerr(fp);
        fd = PerlIO_fileno(fp);
     }
-    if (fd >= 0) {
-       setfd_cloexec(fd);
-       setfd_inhexec_for_sysfd(fd);
-    }
     IoIFP(io) = fp;
 
     IoFLAGS(io) &= ~IOf_NOLINE;
@@ -1100,7 +1096,7 @@ S_openindirtemp(pTHX_ GV *gv, SV *orig_name, SV *temp_out_name) {
 
     {
       int old_umask = umask(0177);
-      fd = Perl_my_mkstemp(SvPVX(temp_out_name));
+      fd = Perl_my_mkstemp_cloexec(SvPVX(temp_out_name));
       umask(old_umask);
     }
 
index 581b6c8..6af7e76 100644 (file)
--- a/embed.fnc
+++ b/embed.fnc
@@ -466,9 +466,11 @@ Ap |bool   |do_open9       |NN GV *gv|NN const char *name|I32 len|int as_raw \
                                |NN SV *svs|I32 num
 pn     |void   |setfd_cloexec|int fd
 pn     |void   |setfd_inhexec|int fd
+p      |void   |setfd_cloexec_for_nonsysfd|int fd
 p      |void   |setfd_inhexec_for_sysfd|int fd
+p      |void   |setfd_cloexec_or_inhexec_by_sysfdness|int fd
 pR     |int    |PerlLIO_dup_cloexec|int oldfd
-pR     |int    |PerlLIO_dup2_cloexec|int oldfd|int newfd
+p      |int    |PerlLIO_dup2_cloexec|int oldfd|int newfd
 pR     |int    |PerlLIO_open_cloexec|NN const char *file|int flag
 pR     |int    |PerlLIO_open3_cloexec|NN const char *file|int flag|int perm
 pnoR   |int    |my_mkstemp_cloexec|NN char *templte
diff --git a/embed.h b/embed.h
index bffd529..b491b76 100644 (file)
--- a/embed.h
+++ b/embed.h
 #define set_numeric_standard() Perl_set_numeric_standard(aTHX)
 #define set_numeric_underlying()       Perl_set_numeric_underlying(aTHX)
 #define setfd_cloexec          Perl_setfd_cloexec
+#define setfd_cloexec_for_nonsysfd(a)  Perl_setfd_cloexec_for_nonsysfd(aTHX_ a)
+#define setfd_cloexec_or_inhexec_by_sysfdness(a)       Perl_setfd_cloexec_or_inhexec_by_sysfdness(aTHX_ a)
 #define setfd_inhexec          Perl_setfd_inhexec
 #define setfd_inhexec_for_sysfd(a)     Perl_setfd_inhexec_for_sysfd(aTHX_ a)
 #define sub_crush_depth(a)     Perl_sub_crush_depth(aTHX_ a)
diff --git a/perl.c b/perl.c
index 2fca0f4..a4e0d19 100644 (file)
--- a/perl.c
+++ b/perl.c
@@ -841,7 +841,7 @@ perl_destruct(pTHXx)
                   back into Perl_debug_log, as if we never actually closed it
                */
                if(got_fd != debug_fd) {
-                   if (dup2(got_fd, debug_fd) == -1) {
+                   if (PerlLIO_dup2_cloexec(got_fd, debug_fd) == -1) {
                        where = "dup2";
                        goto abort;
                    }
@@ -4059,8 +4059,6 @@ S_open_script(pTHX_ const char *scriptname, bool dosearch, bool *suidscript)
                    CopFILE(PL_curcop), Strerror(errno));
     }
     fd = PerlIO_fileno(rsfp);
-    if (fd >= 0)
-       setfd_cloexec(fd);
 
     if (fd < 0 ||
         (PerlLIO_fstat(fd, &tmpstatbuf) >= 0
index fa9f54f..f5eb485 100644 (file)
--- a/perlio.c
+++ b/perlio.c
@@ -245,7 +245,7 @@ PerlIO_fdupopen(pTHX_ PerlIO *f, CLONE_PARAMS *param, int flags)
     return win32_fdupopen(f);
 # else
     if (f) {
-       const int fd = PerlLIO_dup(PerlIO_fileno(f));
+       const int fd = PerlLIO_dup_cloexec(PerlIO_fileno(f));
        if (fd >= 0) {
            char mode[8];
 #  ifdef DJGPP
@@ -289,7 +289,7 @@ PerlIO_openn(pTHX_ const char *layers, const char *mode, int fd,
                 return NULL;
 
            if (*mode == IoTYPE_NUMERIC) {
-               fd = PerlLIO_open3(name, imode, perm);
+               fd = PerlLIO_open3_cloexec(name, imode, perm);
                if (fd >= 0)
                    return PerlIO_fdopen(fd, mode + 1);
            }
@@ -2642,6 +2642,7 @@ PerlIOUnix_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
                IV n, const char *mode, int fd, int imode,
                int perm, PerlIO *f, int narg, SV **args)
 {
+    bool known_cloexec = 0;
     if (PerlIOValid(f)) {
        if (PerlIOBase(f)->tab && PerlIOBase(f)->flags & PERLIO_F_OPEN)
            (*PerlIOBase(f)->tab->Close)(aTHX_ f);
@@ -2662,10 +2663,15 @@ PerlIOUnix_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
            const char *path = SvPV_const(*args, len);
            if (!IS_SAFE_PATHNAME(path, len, "open"))
                 return NULL;
-           fd = PerlLIO_open3(path, imode, perm);
+           fd = PerlLIO_open3_cloexec(path, imode, perm);
+           known_cloexec = 1;
        }
     }
     if (fd >= 0) {
+       if (known_cloexec)
+           setfd_inhexec_for_sysfd(fd);
+       else
+           setfd_cloexec_or_inhexec_by_sysfdness(fd);
        if (*mode == IoTYPE_IMPLICIT)
            mode++;
        if (!f) {
@@ -2700,7 +2706,9 @@ PerlIOUnix_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
     const PerlIOUnix * const os = PerlIOSelf(o, PerlIOUnix);
     int fd = os->fd;
     if (flags & PERLIO_DUP_FD) {
-       fd = PerlLIO_dup(fd);
+       fd = PerlLIO_dup_cloexec(fd);
+       if (fd >= 0)
+           setfd_inhexec_for_sysfd(fd);
     }
     if (fd >= 0) {
        f = PerlIOBase_dup(aTHX_ f, o, param, flags);
@@ -2964,7 +2972,7 @@ PerlIO_importFILE(FILE *stdio, const char *mode)
               Note that the errno value set by a failing fdopen
               varies between stdio implementations.
             */
-            const int fd = PerlLIO_dup(fd0);
+            const int fd = PerlLIO_dup_cloexec(fd0);
            FILE *f2;
             if (fd < 0) {
                 return f;
@@ -2986,11 +2994,12 @@ PerlIO_importFILE(FILE *stdio, const char *mode)
        if ((f = PerlIO_push(aTHX_(PerlIO_allocate(aTHX)), PERLIO_FUNCS_CAST(&PerlIO_stdio), mode, NULL))) {
            s = PerlIOSelf(f, PerlIOStdio);
            s->stdio = stdio;
+           fd0 = fileno(stdio);
+           if(fd0 != -1){
+               PerlIOUnix_refcnt_inc(fd0);
+               setfd_cloexec_or_inhexec_by_sysfdness(fd0);
+           }
 #ifdef EBCDIC
-               fd0 = fileno(stdio);
-               if(fd0 != -1){
-                       PerlIOUnix_refcnt_inc(fd0);
-               }
                else{
                        rc = fldata(stdio,filename,&fileinfo);
                        if(rc != 0){
@@ -3001,8 +3010,6 @@ PerlIO_importFILE(FILE *stdio, const char *mode)
                        }
                          /*This MVS dataset , OK!*/
                }
-#else
-           PerlIOUnix_refcnt_inc(fileno(stdio));
 #endif
        }
     }
@@ -3028,7 +3035,9 @@ PerlIOStdio_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
        if (!s->stdio)
            return NULL;
        s->stdio = stdio;
-       PerlIOUnix_refcnt_inc(fileno(s->stdio));
+       fd = fileno(stdio);
+       PerlIOUnix_refcnt_inc(fd);
+       setfd_cloexec_or_inhexec_by_sysfdness(fd);
        return f;
     }
     else {
@@ -3039,7 +3048,7 @@ PerlIOStdio_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
                 return NULL;
            if (*mode == IoTYPE_NUMERIC) {
                mode++;
-               fd = PerlLIO_open3(path, imode, perm);
+               fd = PerlLIO_open3_cloexec(path, imode, perm);
            }
            else {
                FILE *stdio;
@@ -3059,7 +3068,9 @@ PerlIOStdio_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
                    f = PerlIO_push(aTHX_ f, self, mode, PerlIOArg);
                    if (f) {
                        PerlIOSelf(f, PerlIOStdio)->stdio = stdio;
-                       PerlIOUnix_refcnt_inc(fileno(stdio));
+                       fd = fileno(stdio);
+                       PerlIOUnix_refcnt_inc(fd);
+                       setfd_cloexec_or_inhexec_by_sysfdness(fd);
                    } else {
                        PerlSIO_fclose(stdio);
                    }
@@ -3100,7 +3111,9 @@ PerlIOStdio_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
                }
                if ((f = PerlIO_push(aTHX_ f, self, mode, PerlIOArg))) {
                    PerlIOSelf(f, PerlIOStdio)->stdio = stdio;
-                   PerlIOUnix_refcnt_inc(fileno(stdio));
+                   fd = fileno(stdio);
+                   PerlIOUnix_refcnt_inc(fd);
+                   setfd_cloexec_or_inhexec_by_sysfdness(fd);
                }
                return f;
            }
@@ -3121,7 +3134,7 @@ PerlIOStdio_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
        const int fd = fileno(stdio);
        char mode[8];
        if (flags & PERLIO_DUP_FD) {
-           const int dfd = PerlLIO_dup(fileno(stdio));
+           const int dfd = PerlLIO_dup_cloexec(fileno(stdio));
            if (dfd >= 0) {
                stdio = PerlSIO_fdopen(dfd, PerlIO_modestr(o,mode));
                goto set_this;
@@ -3137,7 +3150,9 @@ PerlIOStdio_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
     set_this:
        PerlIOSelf(f, PerlIOStdio)->stdio = stdio;
         if(stdio) {
-           PerlIOUnix_refcnt_inc(fileno(stdio));
+           int fd = fileno(stdio);
+           PerlIOUnix_refcnt_inc(fd);
+           setfd_cloexec_or_inhexec_by_sysfdness(fd);
         }
     }
     return f;
@@ -3294,7 +3309,7 @@ PerlIOStdio_close(pTHX_ PerlIO *f)
            SAVE_ERRNO;
            invalidate = PerlIOStdio_invalidate_fileno(aTHX_ stdio);
            if (!invalidate) {
-               dupfd = PerlLIO_dup(fd);
+               dupfd = PerlLIO_dup_cloexec(fd);
 #ifdef USE_ITHREADS
                if (dupfd < 0) {
                    /* Oh cXap. This isn't going to go well. Not sure if we can
@@ -3319,7 +3334,8 @@ PerlIOStdio_close(pTHX_ PerlIO *f)
        result = close(fd);
 #endif
        if (dupfd >= 0) {
-           PerlLIO_dup2(dupfd,fd);
+           PerlLIO_dup2_cloexec(dupfd, fd);
+           setfd_inhexec_for_sysfd(fd);
            PerlLIO_close(dupfd);
        }
         MUTEX_UNLOCK(&PL_perlio_mutex);
@@ -5039,19 +5055,19 @@ PerlIO_tmpfile(void)
         /* if TMPDIR is set and not empty, we try that first */
         sv = newSVpv(tmpdir, 0);
         sv_catpv(sv, tempname + 4);
-        fd = Perl_my_mkstemp(SvPVX(sv));
+        fd = Perl_my_mkstemp_cloexec(SvPVX(sv));
      }
      if (fd < 0) {
         SvREFCNT_dec(sv);
         sv = NULL;
         /* else we try /tmp */
-        fd = Perl_my_mkstemp(tempname);
+        fd = Perl_my_mkstemp_cloexec(tempname);
      }
      if (fd < 0) {
          /* Try cwd */
          sv = newSVpvs(".");
          sv_catpv(sv, tempname + 4);
-         fd = Perl_my_mkstemp(SvPVX(sv));
+         fd = Perl_my_mkstemp_cloexec(SvPVX(sv));
      }
      umask(old_umask);
      if (fd >= 0) {
index 55aaf14..b70a510 100644 (file)
@@ -505,6 +505,14 @@ arguments passed to them, I<n> is the index into that array of the
 layer being called. The macro C<PerlIOArg> will return a (possibly
 C<NULL>) SV * for the argument passed to the layer.
 
+Where a layer opens or takes ownership of a file descriptor, that layer is
+responsible for getting the file descriptor's close-on-exec flag into the
+correct state.  The flag should be clear for a file descriptor numbered
+less than or equal to C<PL_maxsysfd>, and set for any file descriptor
+numbered higher.  For thread safety, when a layer opens a new file
+descriptor it should if possible open it with the close-on-exec flag
+initially set.
+
 The I<mode> string is an "C<fopen()>-like" string which would match
 the regular expression C</^[I#]?[rwa]\+?[bt]?$/>.
 
@@ -525,6 +533,9 @@ If I<fd> not negative then it is the numeric file descriptor I<fd>,
 which will be open in a manner compatible with the supplied mode
 string, the call is thus equivalent to C<PerlIO_fdopen>. In this case
 I<nargs> will be zero.
+The file descriptor may have the close-on-exec flag either set or clear;
+it is the responsibility of the layer that takes ownership of it to get
+the flag into the correct state.
 
 If I<nargs> is greater than zero then it gives the number of arguments
 passed to C<open>, otherwise it will be 1 if for example
index c2873b8..0c9147b 100644 (file)
--- a/pp_sys.c
+++ b/pp_sys.c
@@ -692,8 +692,6 @@ PP(pp_pipe_op)
 
     if (PerlProc_pipe_cloexec(fd) < 0)
        goto badexit;
-    setfd_inhexec_for_sysfd(fd[0]);
-    setfd_inhexec_for_sysfd(fd[1]);
 
     IoIFP(rstio) = PerlIO_fdopen(fd[0], "r" PIPE_OPEN_MODE);
     IoOFP(wstio) = PerlIO_fdopen(fd[1], "w" PIPE_OPEN_MODE);
@@ -2521,7 +2519,6 @@ PP(pp_socket)
     if (fd < 0) {
        RETPUSHUNDEF;
     }
-    setfd_inhexec_for_sysfd(fd);
     IoIFP(io) = PerlIO_fdopen(fd, "r" SOCKET_OPEN_MODE); /* stdio gets confused about sockets */
     IoOFP(io) = PerlIO_fdopen(fd, "w" SOCKET_OPEN_MODE);
     IoTYPE(io) = IoTYPE_SOCKET;
@@ -2558,8 +2555,6 @@ PP(pp_sockpair)
     TAINT_PROPER("socketpair");
     if (PerlSock_socketpair_cloexec(domain, type, protocol, fd) < 0)
        RETPUSHUNDEF;
-    setfd_inhexec_for_sysfd(fd[0]);
-    setfd_inhexec_for_sysfd(fd[1]);
     IoIFP(io1) = PerlIO_fdopen(fd[0], "r" SOCKET_OPEN_MODE);
     IoOFP(io1) = PerlIO_fdopen(fd[0], "w" SOCKET_OPEN_MODE);
     IoTYPE(io1) = IoTYPE_SOCKET;
@@ -2675,7 +2670,6 @@ PP(pp_accept)
 
     if (fd < 0)
        goto badexit;
-    setfd_inhexec_for_sysfd(fd);
     if (IoIFP(nstio))
        do_close(ngv, FALSE);
     IoIFP(nstio) = PerlIO_fdopen(fd, "r" SOCKET_OPEN_MODE);
diff --git a/proto.h b/proto.h
index 2c87e88..18ba0a1 100644 (file)
--- a/proto.h
+++ b/proto.h
@@ -35,9 +35,7 @@ PERL_CALLCONV UV      NATIVE_TO_NEED(const UV enc, const UV ch)
 #endif
 
 PERL_CALLCONV const char *     Perl_PerlIO_context_layers(pTHX_ const char *mode);
-PERL_CALLCONV int      Perl_PerlLIO_dup2_cloexec(pTHX_ int oldfd, int newfd)
-                       __attribute__warn_unused_result__;
-
+PERL_CALLCONV int      Perl_PerlLIO_dup2_cloexec(pTHX_ int oldfd, int newfd);
 PERL_CALLCONV int      Perl_PerlLIO_dup_cloexec(pTHX_ int oldfd)
                        __attribute__warn_unused_result__;
 
@@ -2934,6 +2932,8 @@ PERL_CALLCONV void        Perl_setdefout(pTHX_ GV* gv);
 #define PERL_ARGS_ASSERT_SETDEFOUT     \
        assert(gv)
 PERL_CALLCONV void     Perl_setfd_cloexec(int fd);
+PERL_CALLCONV void     Perl_setfd_cloexec_for_nonsysfd(pTHX_ int fd);
+PERL_CALLCONV void     Perl_setfd_cloexec_or_inhexec_by_sysfdness(pTHX_ int fd);
 PERL_CALLCONV void     Perl_setfd_inhexec(int fd);
 PERL_CALLCONV void     Perl_setfd_inhexec_for_sysfd(pTHX_ int fd);
 PERL_CALLCONV char*    Perl_setlocale(int category, const char* locale);
diff --git a/toke.c b/toke.c
index eea1a79..1519d41 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -7668,11 +7668,6 @@ Perl_yylex(pTHX)
                if (!GvIO(gv))
                    GvIOp(gv) = newIO();
                IoIFP(GvIOp(gv)) = PL_rsfp;
-               {
-                   const int fd = PerlIO_fileno(PL_rsfp);
-                    if (fd >= 3)
-                       setfd_cloexec(fd);
-               }
                /* Mark this internal pseudo-handle as clean */
                IoFLAGS(GvIOp(gv)) |= IOf_UNTAINT;
                if ((PerlIO*)PL_rsfp == PerlIO_stdin())
diff --git a/util.c b/util.c
index 14f9204..41aadca 100644 (file)
--- a/util.c
+++ b/util.c
@@ -2238,7 +2238,7 @@ Perl_my_popen_list(pTHX_ const char *mode, int n, SV **args)
        taint_env();
        taint_proper("Insecure %s%s", "EXEC");
     }
-    if (PerlProc_pipe(p) < 0)
+    if (PerlProc_pipe_cloexec(p) < 0)
        return NULL;
     /* Try for another pipe pair for error return */
     if (PerlProc_pipe_cloexec(pp) >= 0)
@@ -2298,7 +2298,7 @@ Perl_my_popen_list(pTHX_ const char *mode, int n, SV **args)
        PerlLIO_close(pp[1]);
     /* Keep the lower of the two fd numbers */
     if (p[that] < p[This]) {
-       PerlLIO_dup2(p[This], p[that]);
+       PerlLIO_dup2_cloexec(p[This], p[that]);
        PerlLIO_close(p[This]);
        p[This] = p[that];
     }
@@ -2378,7 +2378,7 @@ Perl_my_popen(pTHX_ const char *cmd, const char *mode)
        taint_env();
        taint_proper("Insecure %s%s", "EXEC");
     }
-    if (PerlProc_pipe(p) < 0)
+    if (PerlProc_pipe_cloexec(p) < 0)
        return NULL;
     if (doexec && PerlProc_pipe_cloexec(pp) >= 0)
        did_pipes = 1;
@@ -2450,7 +2450,7 @@ Perl_my_popen(pTHX_ const char *cmd, const char *mode)
     if (did_pipes)
        PerlLIO_close(pp[1]);
     if (p[that] < p[This]) {
-       PerlLIO_dup2(p[This], p[that]);
+       PerlLIO_dup2_cloexec(p[This], p[that]);
        PerlLIO_close(p[This]);
        p[This] = p[that];
     }