summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJarkko Hietaniemi <jhi@iki.fi>2002-07-07 17:04:27 +0000
committerJarkko Hietaniemi <jhi@iki.fi>2002-07-07 17:04:27 +0000
commit650375fe384cb56dbced4fc42b30d62c1977e193 (patch)
tree5a27fdb42e8271099b018513e9f3beb567d5b613
parentf9a08e12cdb44672657c74b71978f8d93dc05195 (diff)
downloadperl-650375fe384cb56dbced4fc42b30d62c1977e193.tar.gz
Integrate maint patches #13474, #13478, #13584, and #16539;
introduce the test case of [ID 20020623.009]. Once upon a time #13474 introduced evil coredumps, but now things seem to be better (tried both with and without ithreads). p4raw-id: //depot/perl@17407 p4raw-edited: from //depot/maint-5.6/perl@17406 'ignore' op.c (@14778..)
-rw-r--r--op.c47
-rw-r--r--t/run/fresh_perl.t13
2 files changed, 55 insertions, 5 deletions
diff --git a/op.c b/op.c
index 9a53f07e39..850983b3b4 100644
--- a/op.c
+++ b/op.c
@@ -4348,6 +4348,10 @@ Perl_newLOOPEX(pTHX_ I32 type, OP *label)
void
Perl_cv_undef(pTHX_ CV *cv)
{
+ CV *outsidecv;
+ CV *freecv = Nullcv;
+ bool is_eval = CvEVAL(cv) && !CvGV(cv); /* is this eval"" ? */
+
#ifdef USE_5005THREADS
if (CvMUTEXP(cv)) {
MUTEX_DESTROY(CvMUTEXP(cv));
@@ -4383,13 +4387,14 @@ Perl_cv_undef(pTHX_ CV *cv)
}
SvPOK_off((SV*)cv); /* forget prototype */
CvGV(cv) = Nullgv;
+ outsidecv = CvOUTSIDE(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))
- SvREFCNT_dec(CvOUTSIDE(cv));
+ freecv = outsidecv;
CvOUTSIDE(cv) = Nullcv;
if (CvCONST(cv)) {
SvREFCNT_dec((SV*)CvXSUBANY(cv).any_ptr);
@@ -4398,10 +4403,40 @@ Perl_cv_undef(pTHX_ CV *cv)
if (CvPADLIST(cv)) {
/* may be during global destruction */
if (SvREFCNT(CvPADLIST(cv))) {
- I32 i = AvFILLp(CvPADLIST(cv));
- while (i >= 0) {
- SV** svp = av_fetch(CvPADLIST(cv), i--, FALSE);
- SV* sv = svp ? *svp : Nullsv;
+ AV *padlist = CvPADLIST(cv);
+ I32 ix;
+ /* pads may be cleared out already during global destruction */
+ if (is_eval && !PL_dirty) {
+ /* inner references to eval's cv must be fixed up */
+ AV *comppad_name = (AV*)AvARRAY(padlist)[0];
+ AV *comppad = (AV*)AvARRAY(padlist)[1];
+ SV **namepad = AvARRAY(comppad_name);
+ SV **curpad = AvARRAY(comppad);
+ for (ix = AvFILLp(comppad_name); ix > 0; ix--) {
+ SV *namesv = namepad[ix];
+ if (namesv && namesv != &PL_sv_undef
+ && *SvPVX(namesv) == '&'
+ && ix <= AvFILLp(comppad))
+ {
+ CV *innercv = (CV*)curpad[ix];
+ if (innercv && SvTYPE(innercv) == SVt_PVCV
+ && CvOUTSIDE(innercv) == cv)
+ {
+ CvOUTSIDE(innercv) = outsidecv;
+ if (!CvANON(innercv) || CvCLONED(innercv)) {
+ (void)SvREFCNT_inc(outsidecv);
+ if (SvREFCNT(cv))
+ SvREFCNT_dec(cv);
+ }
+ }
+ }
+ }
+ }
+ if (freecv)
+ SvREFCNT_dec(freecv);
+ ix = AvFILLp(padlist);
+ while (ix >= 0) {
+ SV* sv = AvARRAY(padlist)[ix--];
if (!sv)
continue;
if (sv == (SV*)PL_comppad_name)
@@ -4416,6 +4451,8 @@ Perl_cv_undef(pTHX_ CV *cv)
}
CvPADLIST(cv) = Nullav;
}
+ else if (freecv)
+ SvREFCNT_dec(freecv);
if (CvXSUB(cv)) {
CvXSUB(cv) = 0;
}
diff --git a/t/run/fresh_perl.t b/t/run/fresh_perl.t
index 3c0a9259ad..9c2b42fc03 100644
--- a/t/run/fresh_perl.t
+++ b/t/run/fresh_perl.t
@@ -831,3 +831,16 @@ $人++; # a child is born
print $人, "\n";
EXPECT
3
+########
+# test that closures generated by eval"" hold on to the CV of the eval""
+# for their entire lifetime
+$code = eval q[
+ sub { eval '$x = "ok 1\n"'; }
+];
+&{$code}();
+print $x;
+EXPECT
+ok 1
+######## [ID 20020623.009] nested eval/sub segfaults
+$eval = eval 'sub { eval "sub { %S }" }';
+$eval->({});