Commit 9a1bb7f1 authored by Niko Tyni's avatar Niko Tyni
Browse files

Add upstream patch fixing file descriptor exhaustion with in-place edits

Closes: #902925
parents b582c42c 4aa4cd67
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
# see git-dpm(1) from git-dpm package
004b7299d16b24e8dbd24dc92eec048484aed8cf
004b7299d16b24e8dbd24dc92eec048484aed8cf
4aa4cd67cdb71691e34cd138d0e25981feedd043
4aa4cd67cdb71691e34cd138d0e25981feedd043
61a74e188b2c62ee2df321fd190ae5375dfadc42
61a74e188b2c62ee2df321fd190ae5375dfadc42
perl_5.28.0.orig.tar.xz
+99 −0
Original line number Diff line number Diff line
From 4aa4cd67cdb71691e34cd138d0e25981feedd043 Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Mon, 2 Jul 2018 10:43:19 +1000
Subject: (perl #133314) always close the directory handle on clean up

Previously the directory handle was only closed if the rest of the
magic free clean up is done, but in most success cases that code
doesn't run, leaking the directory handle.

So always close the directory if our AV is available.

Patch-Name: fixes/in-place-edit-handles.diff
Bug: https://rt.perl.org/Public/Bug/Display.html?id=133314
Bug-Debian: https://bugs.debian.org/902925
Origin: https://rt.perl.org/Ticket/Attachment/1564516/824179/0001-perl-133314-always-close-the-directory-handle-on-cle.patch
---
 doio.c | 56 +++++++++++++++++++++++++++++++-------------------------
 1 file changed, 31 insertions(+), 25 deletions(-)

diff --git a/doio.c b/doio.c
index 4b8923f77..16daf9fd1 100644
--- a/doio.c
+++ b/doio.c
@@ -1163,44 +1163,50 @@ S_argvout_free(pTHX_ SV *io, MAGIC *mg) {
 
     /* mg_obj can be NULL if a thread is created with the handle open, in which
      case we leave any clean up to the parent thread */
-    if (mg->mg_obj && IoIFP(io)) {
-        SV **pid_psv;
+    if (mg->mg_obj) {
 #ifdef ARGV_USE_ATFUNCTIONS
         SV **dir_psv;
         DIR *dir;
+
+        dir_psv = av_fetch((AV*)mg->mg_obj, ARGVMG_ORIG_DIRP, FALSE);
+        assert(dir_psv && *dir_psv && SvIOK(*dir_psv));
+        dir = INT2PTR(DIR *, SvIV(*dir_psv));
 #endif
-        PerlIO *iop = IoIFP(io);
+        if (IoIFP(io)) {
+            SV **pid_psv;
+            PerlIO *iop = IoIFP(io);
 
-        assert(SvTYPE(mg->mg_obj) == SVt_PVAV);
+            assert(SvTYPE(mg->mg_obj) == SVt_PVAV);
 
-        pid_psv = av_fetch((AV*)mg->mg_obj, ARGVMG_ORIG_PID, FALSE);
+            pid_psv = av_fetch((AV*)mg->mg_obj, ARGVMG_ORIG_PID, FALSE);
 
-        assert(pid_psv && *pid_psv);
+            assert(pid_psv && *pid_psv);
 
-        if (SvIV(*pid_psv) == (IV)PerlProc_getpid()) {
-            /* if we get here the file hasn't been closed explicitly by the
-               user and hadn't been closed implicitly by nextargv(), so
-               abandon the edit */
-            SV **temp_psv = av_fetch((AV*)mg->mg_obj, ARGVMG_TEMP_NAME, FALSE);
-            const char *temp_pv = SvPVX(*temp_psv);
+            if (SvIV(*pid_psv) == (IV)PerlProc_getpid()) {
+                /* if we get here the file hasn't been closed explicitly by the
+                   user and hadn't been closed implicitly by nextargv(), so
+                   abandon the edit */
+                SV **temp_psv = av_fetch((AV*)mg->mg_obj, ARGVMG_TEMP_NAME, FALSE);
+                const char *temp_pv = SvPVX(*temp_psv);
 
-            assert(temp_psv && *temp_psv && SvPOK(*temp_psv));
-            (void)PerlIO_close(iop);
-            IoIFP(io) = IoOFP(io) = NULL;
+                assert(temp_psv && *temp_psv && SvPOK(*temp_psv));
+                (void)PerlIO_close(iop);
+                IoIFP(io) = IoOFP(io) = NULL;
 #ifdef ARGV_USE_ATFUNCTIONS
-            dir_psv = av_fetch((AV*)mg->mg_obj, ARGVMG_ORIG_DIRP, FALSE);
-            assert(dir_psv && *dir_psv && SvIOK(*dir_psv));
-            dir = INT2PTR(DIR *, SvIV(*dir_psv));
-            if (dir) {
-                if (unlinkat(my_dirfd(dir), temp_pv, 0) < 0 &&
-                    NotSupported(errno))
-                    (void)UNLINK(temp_pv);
-                closedir(dir);
-            }
+                if (dir) {
+                    if (unlinkat(my_dirfd(dir), temp_pv, 0) < 0 &&
+                        NotSupported(errno))
+                        (void)UNLINK(temp_pv);
+                }
 #else
-            (void)UNLINK(temp_pv);
+                (void)UNLINK(temp_pv);
 #endif
+            }
         }
+#ifdef ARGV_USE_ATFUNCTIONS
+        if (dir)
+            closedir(dir);
+#endif
     }
 
     return 0;
+1 −0
Original line number Diff line number Diff line
@@ -41,3 +41,4 @@ debian/mod_paths.diff
debian/configure-regen.diff
debian/deprecate-with-apt.diff
debian/disable-stack-check.diff
fixes/in-place-edit-handles.diff
+31 −25
Original line number Diff line number Diff line
@@ -1163,12 +1163,17 @@ S_argvout_free(pTHX_ SV *io, MAGIC *mg) {

    /* mg_obj can be NULL if a thread is created with the handle open, in which
     case we leave any clean up to the parent thread */
    if (mg->mg_obj && IoIFP(io)) {
        SV **pid_psv;
    if (mg->mg_obj) {
#ifdef ARGV_USE_ATFUNCTIONS
        SV **dir_psv;
        DIR *dir;

        dir_psv = av_fetch((AV*)mg->mg_obj, ARGVMG_ORIG_DIRP, FALSE);
        assert(dir_psv && *dir_psv && SvIOK(*dir_psv));
        dir = INT2PTR(DIR *, SvIV(*dir_psv));
#endif
        if (IoIFP(io)) {
            SV **pid_psv;
            PerlIO *iop = IoIFP(io);

            assert(SvTYPE(mg->mg_obj) == SVt_PVAV);
@@ -1188,20 +1193,21 @@ S_argvout_free(pTHX_ SV *io, MAGIC *mg) {
                (void)PerlIO_close(iop);
                IoIFP(io) = IoOFP(io) = NULL;
#ifdef ARGV_USE_ATFUNCTIONS
            dir_psv = av_fetch((AV*)mg->mg_obj, ARGVMG_ORIG_DIRP, FALSE);
            assert(dir_psv && *dir_psv && SvIOK(*dir_psv));
            dir = INT2PTR(DIR *, SvIV(*dir_psv));
                if (dir) {
                    if (unlinkat(my_dirfd(dir), temp_pv, 0) < 0 &&
                        NotSupported(errno))
                        (void)UNLINK(temp_pv);
                closedir(dir);
                }
#else
                (void)UNLINK(temp_pv);
#endif
            }
        }
#ifdef ARGV_USE_ATFUNCTIONS
        if (dir)
            closedir(dir);
#endif
    }

    return 0;
}