diff options
author | Nicholas Clark <nick@ccl4.org> | 2012-01-12 23:07:20 +0100 |
---|---|---|
committer | Nicholas Clark <nick@ccl4.org> | 2012-01-13 12:20:49 +0100 |
commit | 9e6704a9c88bca9a5eec456e14f7afa3a21f2181 (patch) | |
tree | 5a422b4915b5109172854b6416d119acd34e3433 /sv.c | |
parent | c6c5075ef3e86920cd3c1ec231855d7ef40fecd1 (diff) | |
download | perl-9e6704a9c88bca9a5eec456e14f7afa3a21f2181.tar.gz |
In Perl_sv_del_backref(), don't panic if svp is NULL during global destruction.
It's possible that the referencing SV is being freed partway through the
freeing of reference target. If this happens, the backreferences array of
the target has already been freed, and so svp will be NULL. If this is the
case, do nothing and return. Previously, this condition was not recognised
and the code would panic.
Diffstat (limited to 'sv.c')
-rw-r--r-- | sv.c | 15 |
1 files changed, 12 insertions, 3 deletions
@@ -5564,9 +5564,18 @@ Perl_sv_del_backref(pTHX_ SV *const tsv, SV *const sv) svp = mg ? &(mg->mg_obj) : NULL; } - if (!svp || !*svp) - Perl_croak(aTHX_ "panic: del_backref, svp=%p, *svp=%p", - svp, svp ? *svp : NULL); + if (!svp) + Perl_croak(aTHX_ "panic: del_backref, svp=0"); + if (!*svp) { + /* It's possible that sv is being freed recursively part way through the + freeing of tsv. If this happens, the backreferences array of tsv has + already been freed, and so svp will be NULL. If this is the case, + we should not panic. Instead, nothing needs doing, so return. */ + if (PL_phase == PERL_PHASE_DESTRUCT && SvREFCNT(tsv) == 0) + return; + Perl_croak(aTHX_ "panic: del_backref, *svp=%p phase=%s refcnt=%" UVuf, + *svp, PL_phase_names[PL_phase], SvREFCNT(tsv)); + } if (SvTYPE(*svp) == SVt_PVAV) { #ifdef DEBUGGING |