summaryrefslogtreecommitdiff
path: root/sv.c
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2012-01-12 22:51:55 +0100
committerNicholas Clark <nick@ccl4.org>2012-01-13 12:20:49 +0100
commitc6c5075ef3e86920cd3c1ec231855d7ef40fecd1 (patch)
treee0d11d032135e6509c74c28445695c5ce3e03e04 /sv.c
parentf69760828c2a1a26995258d477ac4a1da9db2e72 (diff)
downloadperl-c6c5075ef3e86920cd3c1ec231855d7ef40fecd1.tar.gz
In Perl_sv_del_backref(), don't panic if the backref array is already freed.
During global destruction, it's possible for the array containing backreferences to be freed before the SV that owns it. If this happens, don't mistake it for a scalar backreference stored directly, and then get confused and panic because things seem inconsistent. http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2011-12/msg00039.html gives more information.
Diffstat (limited to 'sv.c')
-rw-r--r--sv.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/sv.c b/sv.c
index 7a11a79145..8f623db95f 100644
--- a/sv.c
+++ b/sv.c
@@ -5618,6 +5618,9 @@ Perl_sv_del_backref(pTHX_ SV *const tsv, SV *const sv)
assert(count ==1);
AvFILLp(av) = fill-1;
}
+ else if (SvIS_FREED(*svp) && PL_phase == PERL_PHASE_DESTRUCT) {
+ /* freed AV; skip */
+ }
else {
/* optimisation: only a single backref, stored directly */
if (*svp != sv)