[patch] plug PL_regex_padav leaks
Doug MacEachern [Thu, 2 Aug 2001 20:24:55 +0000 (13:24 -0700)]
Message-ID: <Pine.LNX.4.21.0108022020100.8991-100000@mako.covalent.net>

p4raw-id: //depot/perl@11560

op.c
op.h
perl.c

diff --git a/op.c b/op.c
index 7fad9a4..daefb14 100644 (file)
--- a/op.c
+++ b/op.c
@@ -852,8 +852,14 @@ clear_pmop:
 #endif
        }
        cPMOPo->op_pmreplroot = Nullop;
-       ReREFCNT_dec(PM_GETRE(cPMOPo));
-       PM_SETRE(cPMOPo, (REGEXP*)NULL);
+        /* we use the "SAFE" version of the PM_ macros here
+         * since sv_clean_all might release some PMOPs
+         * after PL_regex_padav has been cleared
+         * and the clearing of PL_regex_padav needs to
+         * happen before sv_clean_all
+         */
+       ReREFCNT_dec(PM_GETRE_SAFE(cPMOPo));
+       PM_SETRE_SAFE(cPMOPo, (REGEXP*)NULL);
        break;
     }
 
diff --git a/op.h b/op.h
index af0e983..e92b1d8 100644 (file)
--- a/op.h
+++ b/op.h
@@ -252,9 +252,13 @@ struct pmop {
 #ifdef USE_ITHREADS
 #define PM_GETRE(o)     ((REGEXP*)SvIVX(PL_regex_pad[(o)->op_pmoffset]))
 #define PM_SETRE(o,r)   (sv_setiv(PL_regex_pad[(o)->op_pmoffset], (IV)r))
+#define PM_GETRE_SAFE(o) (PL_regex_pad ? PM_GETRE(o) : (REGEXP*)0)
+#define PM_SETRE_SAFE(o,r) if (PL_regex_pad) PM_SETRE(o,r)
 #else
 #define PM_GETRE(o)     ((o)->op_pmregexp)
 #define PM_SETRE(o,r)   ((o)->op_pmregexp = (r))
+#define PM_GETRE_SAFE PM_GETRE
+#define PM_SETRE_SAFE PM_SETRE
 #endif
 
 #define PMdf_USED      0x01            /* pm has been used once already */
diff --git a/perl.c b/perl.c
index e6d6f5f..7362316 100644 (file)
--- a/perl.c
+++ b/perl.c
@@ -466,6 +466,28 @@ perl_destruct(pTHXx)
     }
 #endif
 
+#ifdef USE_ITHREADS
+    /* the syntax tree is shared between clones
+     * so op_free(PL_main_root) only ReREFCNT_dec's
+     * REGEXPs in the parent interpreter
+     * we need to manually ReREFCNT_dec for the clones
+     */
+    {
+        I32 i = AvFILLp(PL_regex_padav) + 1;
+        SV **ary = AvARRAY(PL_regex_padav);
+
+        while (i) {
+            REGEXP *re = (REGEXP *)SvIVX(ary[--i]);
+            if (re && (re->refcnt > 0)) {
+                ReREFCNT_dec(re);
+            }
+        }
+    }
+    SvREFCNT_dec(PL_regex_padav);
+    PL_regex_padav = Nullav;
+    PL_regex_pad = NULL;
+#endif
+
     /* loosen bonds of global variables */
 
     if(PL_rsfp) {