The correct solution is to reference count the regexp in PL_reg_curpm,
Nicholas Clark [Thu, 10 Jan 2008 21:16:01 +0000 (21:16 +0000)]
rather than put in lots of hacks to work round not reference counting
it.

p4raw-id: //depot/perl@32938

perl.c
regexec.c

diff --git a/perl.c b/perl.c
index 4442112..a299667 100644 (file)
--- a/perl.c
+++ b/perl.c
@@ -872,23 +872,6 @@ perl_destruct(pTHXx)
      * REGEXPs in the parent interpreter
      * we need to manually ReREFCNT_dec for the clones
      */
-    {
-        I32 i = AvFILLp(PL_regex_padav) + 1;
-        SV * const * const ary = AvARRAY(PL_regex_padav);
-
-        while (i) {
-            SV * const resv = ary[--i];
-
-            if (SvFLAGS(resv) & SVf_BREAK) {
-                /* this is PL_reg_curpm, already freed
-                 * flag is set in regexec.c:S_regtry
-                 */
-                SvFLAGS(resv) &= ~SVf_BREAK;
-               /* So stop it pointing to what is now a dead reference.  */
-               SvROK_off(resv);
-            }
-        }
-    }
     SvREFCNT_dec(PL_regex_padav);
     PL_regex_padav = NULL;
     PL_regex_pad = NULL;
index 9a41f20..5ce1ee3 100644 (file)
--- a/regexec.c
+++ b/regexec.c
@@ -2256,15 +2256,18 @@ S_regtry(pTHX_ regmatch_info *reginfo, char **startpos)
 #ifdef USE_ITHREADS
             {
                SV* const repointer = newSViv(0);
-                /* so we know which PL_regex_padav element is PL_reg_curpm
-                  when clearing up in perl_destruct() */
-                SvFLAGS(repointer) |= SVf_BREAK;
+                /* this regexp is also owned by the new PL_reg_curpm, which
+                  will try to free it.  */
                 av_push(PL_regex_padav, repointer);
                 PL_reg_curpm->op_pmoffset = av_len(PL_regex_padav);
                 PL_regex_pad = AvARRAY(PL_regex_padav);
             }
 #endif      
         }
+       /* This is safe against NULLs: */
+       ReREFCNT_dec(PM_GETRE(PL_reg_curpm));
+       /* PM_reg_curpm owns a reference to this regexp.  */
+       ReREFCNT_inc(rx);
        PM_SETRE(PL_reg_curpm, rx);
        PL_reg_oldcurpm = PL_curpm;
        PL_curpm = PL_reg_curpm;