From: Vincent Pit Date: Sat, 23 Jun 2012 21:39:11 +0000 (+0200) Subject: Don't leak vtables and wizards freed during global destruction X-Git-Tag: rt77991~6 X-Git-Url: http://git.vpit.fr/?p=perl%2Fmodules%2FVariable-Magic.git;a=commitdiff_plain;h=d67d5aa3c48466b4302b1e9be9fe31e032ca48f2 Don't leak vtables and wizards freed during global destruction At this time, we cannot access the callbacks, but we are still allowed to call Safefree() and PerlMemShared_free(). --- diff --git a/Magic.xs b/Magic.xs index 8aee17b..59eaa75 100644 --- a/Magic.xs +++ b/Magic.xs @@ -522,26 +522,32 @@ STATIC void vmg_wizard_free(pTHX_ vmg_wizard *w) { if (!w) return; - SvREFCNT_dec(w->cb_data); - SvREFCNT_dec(w->cb_get); - SvREFCNT_dec(w->cb_set); - SvREFCNT_dec(w->cb_len); - SvREFCNT_dec(w->cb_clear); - SvREFCNT_dec(w->cb_free); - SvREFCNT_dec(w->cb_copy); + /* During global destruction, any of the callbacks may already have been + * freed, so we can't rely on still being able to access them. */ + if (!PL_dirty) { + SvREFCNT_dec(w->cb_data); + SvREFCNT_dec(w->cb_get); + SvREFCNT_dec(w->cb_set); + SvREFCNT_dec(w->cb_len); + SvREFCNT_dec(w->cb_clear); + SvREFCNT_dec(w->cb_free); + SvREFCNT_dec(w->cb_copy); #if 0 - SvREFCNT_dec(w->cb_dup); + SvREFCNT_dec(w->cb_dup); #endif #if MGf_LOCAL - SvREFCNT_dec(w->cb_local); + SvREFCNT_dec(w->cb_local); #endif /* MGf_LOCAL */ #if VMG_UVAR - SvREFCNT_dec(w->cb_fetch); - SvREFCNT_dec(w->cb_store); - SvREFCNT_dec(w->cb_exists); - SvREFCNT_dec(w->cb_delete); + SvREFCNT_dec(w->cb_fetch); + SvREFCNT_dec(w->cb_store); + SvREFCNT_dec(w->cb_exists); + SvREFCNT_dec(w->cb_delete); #endif /* VMG_UVAR */ + } + /* PerlMemShared_free() and Safefree() are still fine during global + * destruction though. */ vmg_vtable_free(w->vtable); Safefree(w); @@ -595,9 +601,6 @@ STATIC const vmg_wizard *vmg_wizard_dup(pTHX_ const vmg_wizard *w, CLONE_PARAMS /* --- Wizard SV objects --------------------------------------------------- */ STATIC int vmg_wizard_sv_free(pTHX_ SV *sv, MAGIC *mg) { - if (PL_dirty) /* During global destruction, the context is already freed */ - return 0; - vmg_wizard_free((vmg_wizard *) mg->mg_ptr); return 0; @@ -1187,8 +1190,8 @@ STATIC int vmg_svt_free(pTHX_ SV *sv, MAGIC *mg) { dSP; - /* Don't even bother if we are in global destruction - the wizard is prisoner - * of circular references and we are way beyond user realm */ + /* During global destruction, we cannot be sure that the wizard and its free + * callback are still alive. */ if (PL_dirty) return 0;