summaryrefslogtreecommitdiff
path: root/op.c
diff options
context:
space:
mode:
authorDave Mitchell <davem@fdisolutions.com>2002-12-10 01:26:44 +0000
committerRafael Garcia-Suarez <rgarciasuarez@gmail.com>2002-12-14 22:34:25 +0000
commit7dafbf5232bace07a044625a5a956b73da3928d5 (patch)
tree5042129d851b4706c4c22a7c67de6b3092bc08cb /op.c
parent0412d5267fa2300f66eb4eb554e2af493b5e5b33 (diff)
downloadperl-7dafbf5232bace07a044625a5a956b73da3928d5.tar.gz
Proper fix for CvOUTSIDE weak refcounting
Message-ID: <20021210012644.A7843@fdgroup.com> p4raw-id: //depot/perl@18302
Diffstat (limited to 'op.c')
-rw-r--r--op.c39
1 files changed, 19 insertions, 20 deletions
diff --git a/op.c b/op.c
index c46bbfce0e..46347da306 100644
--- a/op.c
+++ b/op.c
@@ -3753,11 +3753,20 @@ Perl_newLOOPEX(pTHX_ I32 type, OP *label)
return o;
}
+/*
+=for apidoc cv_undef
+
+Clear out all the active components of a CV. This can happen either
+by an explicit C<undef &foo>, or by the reference count going to zero.
+In the former case, we keep the CvOUTSIDE pointer, so that any anonymous
+children can still follow the full lexical scope chain.
+
+=cut
+*/
+
void
Perl_cv_undef(pTHX_ CV *cv)
{
- CV *freecv = Nullcv;
-
#ifdef USE_ITHREADS
if (CvFILE(cv) && !CvXSUB(cv)) {
/* for XSUBs CvFILE point directly to static memory; __FILE__ */
@@ -3782,24 +3791,21 @@ Perl_cv_undef(pTHX_ CV *cv)
pad_undef(cv);
- /* Since closure prototypes have the same lifetime as the containing
- * CV, they don't hold a refcount on the outside CV. This avoids
- * the refcount loop between the outer CV (which keeps a refcount to
- * the closure prototype in the pad entry for pp_anoncode()) and the
- * closure prototype, and the ensuing memory leak. --GSAR */
- if (!CvANON(cv) || CvCLONED(cv))
- freecv = CvOUTSIDE(cv);
- CvOUTSIDE(cv) = Nullcv;
+ /* remove CvOUTSIDE unless this is an undef rather than a free */
+ if (!SvREFCNT(cv) && CvOUTSIDE(cv)) {
+ if (!CvWEAKOUTSIDE(cv))
+ SvREFCNT_dec(CvOUTSIDE(cv));
+ CvOUTSIDE(cv) = Nullcv;
+ }
if (CvCONST(cv)) {
SvREFCNT_dec((SV*)CvXSUBANY(cv).any_ptr);
CvCONST_off(cv);
}
- if (freecv)
- SvREFCNT_dec(freecv);
if (CvXSUB(cv)) {
CvXSUB(cv) = 0;
}
- CvFLAGS(cv) = 0;
+ /* delete all flags except WEAKOUTSIDE */
+ CvFLAGS(cv) &= CVf_WEAKOUTSIDE;
}
void
@@ -4161,13 +4167,6 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
CvCONST_on(cv);
}
- /* If a potential closure prototype, don't keep a refcount on outer CV.
- * This is okay as the lifetime of the prototype is tied to the
- * lifetime of the outer CV. Avoids memory leak due to reference
- * loop. --GSAR */
- if (!name)
- SvREFCNT_dec(CvOUTSIDE(cv));
-
if (name || aname) {
char *s;
char *tname = (name ? name : aname);