POPSUB() gave up the refcount to the CV before LEAVE had a chance to
Gurusamy Sarathy [Sat, 9 Oct 1999 00:41:02 +0000 (00:41 +0000)]
clear entries in the CV's pad, leading to coredumps when CV had no
other references to it; this is a slightly edited version of the
patch suggested by Russel O'Connor <roconnor@world.std.com>

p4raw-id: //depot/perl@4321

cop.h
pp_ctl.c
pp_hot.c

diff --git a/cop.h b/cop.h
index 88749fb..457aeb4 100644 (file)
--- a/cop.h
+++ b/cop.h
@@ -62,7 +62,8 @@ struct block_sub {
     } STMT_END
 #endif /* USE_THREADS */
 
-#define POPSUB(cx)                                                     \
+#define POPSUB(cx,sv)                                                  \
+    STMT_START {                                                       \
        if (cx->blk_sub.hasargs) {                                      \
            POPSAVEARRAY();                                             \
            /* abandon @_ if it got reified */                          \
@@ -75,10 +76,16 @@ struct block_sub {
                PL_curpad[0] = (SV*)cx->blk_sub.argarray;               \
            }                                                           \
        }                                                               \
-       if (cx->blk_sub.cv) {                                           \
-           if (!(CvDEPTH(cx->blk_sub.cv) = cx->blk_sub.olddepth))      \
-               SvREFCNT_dec(cx->blk_sub.cv);                           \
-       }
+       sv = (SV*)cx->blk_sub.cv;                                       \
+       if (sv && (CvDEPTH((CV*)sv) = cx->blk_sub.olddepth))            \
+           sv = Nullsv;                                                \
+    } STMT_END
+
+#define LEAVESUB(sv)                                                   \
+    STMT_START {                                                       \
+       if (sv)                                                         \
+           SvREFCNT_dec(sv);                                           \
+    } STMT_END
 
 #define POPFORMAT(cx)                                                  \
        setdefout(cx->blk_sub.dfoutgv);                                 \
index 746cb80..3bf4f1d 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -1187,6 +1187,7 @@ Perl_dounwind(pTHX_ I32 cxix)
     I32 optype;
 
     while (cxstack_ix > cxix) {
+       SV *sv;
        cx = &cxstack[cxstack_ix];
        DEBUG_l(PerlIO_printf(Perl_debug_log, "Unwinding block %ld, type %s\n",
                              (long) cxstack_ix, PL_block_type[CxTYPE(cx)]));
@@ -1196,7 +1197,8 @@ Perl_dounwind(pTHX_ I32 cxix)
            POPSUBST(cx);
            continue;  /* not break */
        case CXt_SUB:
-           POPSUB(cx);
+           POPSUB(cx,sv);
+           LEAVESUB(sv);
            break;
        case CXt_EVAL:
            POPEVAL(cx);
@@ -1700,6 +1702,7 @@ PP(pp_return)
     SV **newsp;
     PMOP *newpm;
     I32 optype = 0;
+    SV *sv;
 
     if (PL_curstackinfo->si_type == PERLSI_SORT) {
        if (cxstack_ix == PL_sortcxix || dopoptosub(cxstack_ix) <= PL_sortcxix) {
@@ -1771,11 +1774,14 @@ PP(pp_return)
 
     /* Stack values are safe: */
     if (popsub2) {
-       POPSUB(cx);     /* release CV and @_ ... */
+       POPSUB(cx,sv);  /* release CV and @_ ... */
     }
+    else
+       sv = Nullsv;
     PL_curpm = newpm;  /* ... and pop $1 et al */
 
     LEAVE;
+    LEAVESUB(sv);
     return pop_return();
 }
 
@@ -1791,6 +1797,7 @@ PP(pp_last)
     SV **newsp;
     PMOP *newpm;
     SV **mark;
+    SV *sv = Nullsv;
 
     if (PL_op->op_flags & OPf_SPECIAL) {
        cxix = dopoptoloop(cxstack_ix);
@@ -1850,12 +1857,13 @@ PP(pp_last)
        LEAVE;
        break;
     case CXt_SUB:
-       POPSUB(cx);     /* release CV and @_ ... */
+       POPSUB(cx,sv);  /* release CV and @_ ... */
        break;
     }
     PL_curpm = newpm;  /* ... and pop $1 et al */
 
     LEAVE;
+    LEAVESUB(sv);
     return nextop;
 }
 
index 90e8f5f..78a454c 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -1914,6 +1914,7 @@ PP(pp_leavesub)
     PMOP *newpm;
     I32 gimme;
     register PERL_CONTEXT *cx;
+    SV *sv;
 
     POPBLOCK(cx,newpm);
  
@@ -1951,10 +1952,11 @@ PP(pp_leavesub)
     }
     PUTBACK;
     
-    POPSUB(cx);                /* Stack values are safe: release CV and @_ ... */
+    POPSUB(cx,sv);     /* Stack values are safe: release CV and @_ ... */
     PL_curpm = newpm;  /* ... and pop $1 et al */
 
     LEAVE;
+    LEAVESUB(sv);
     return pop_return();
 }
 
@@ -1968,6 +1970,7 @@ PP(pp_leavesublv)
     PMOP *newpm;
     I32 gimme;
     register PERL_CONTEXT *cx;
+    SV *sv;
 
     POPBLOCK(cx,newpm);
  
@@ -2005,8 +2008,10 @@ PP(pp_leavesublv)
         * the refcounts so the caller gets a live guy. Cannot set
         * TEMP, so sv_2mortal is out of question. */
        if (!CvLVALUE(cx->blk_sub.cv)) {
-           POPSUB(cx);
+           POPSUB(cx,sv);
            PL_curpm = newpm;
+           LEAVE;
+           LEAVESUB(sv);
            DIE(aTHX_ "Can't modify non-lvalue subroutine call");
        }
        if (gimme == G_SCALAR) {
@@ -2014,8 +2019,10 @@ PP(pp_leavesublv)
            EXTEND_MORTAL(1);
            if (MARK == SP) {
                if (SvFLAGS(TOPs) & (SVs_TEMP | SVs_PADTMP | SVf_READONLY)) {
-                   POPSUB(cx);
+                   POPSUB(cx,sv);
                    PL_curpm = newpm;
+                   LEAVE;
+                   LEAVESUB(sv);
                    DIE(aTHX_ "Can't return a %s from lvalue subroutine",
                        SvREADONLY(TOPs) ? "readonly value" : "temporary");
                }
@@ -2026,8 +2033,10 @@ PP(pp_leavesublv)
                }
            }
            else {                      /* Should not happen? */
-               POPSUB(cx);
+               POPSUB(cx,sv);
                PL_curpm = newpm;
+               LEAVE;
+               LEAVESUB(sv);
                DIE(aTHX_ "%s returned from lvalue subroutine in scalar context",
                    (MARK > SP ? "Empty array" : "Array"));
            }
@@ -2039,8 +2048,10 @@ PP(pp_leavesublv)
                if (SvFLAGS(*mark) & (SVs_TEMP | SVs_PADTMP | SVf_READONLY)) {
                    /* Might be flattened array after $#array =  */
                    PUTBACK;
-                   POPSUB(cx);
+                   POPSUB(cx,sv);
                    PL_curpm = newpm;
+                   LEAVE;
+                   LEAVESUB(sv);
                    DIE(aTHX_ "Can't return %s from lvalue subroutine",
                        (*mark != &PL_sv_undef)
                        ? (SvREADONLY(TOPs)
@@ -2093,10 +2104,11 @@ PP(pp_leavesublv)
     }
     PUTBACK;
     
-    POPSUB(cx);                /* Stack values are safe: release CV and @_ ... */
+    POPSUB(cx,sv);     /* Stack values are safe: release CV and @_ ... */
     PL_curpm = newpm;  /* ... and pop $1 et al */
 
     LEAVE;
+    LEAVESUB(sv);
     return pop_return();
 }