From: Vincent Pit Date: Sat, 14 Feb 2009 15:31:09 +0000 (+0100) Subject: Reference count vmg_op_name_len X-Git-Tag: v0.31~11 X-Git-Url: http://git.vpit.fr/?p=perl%2Fmodules%2FVariable-Magic.git;a=commitdiff_plain;h=439d151ce8d86e0e77c82b85538305ace71ba630 Reference count vmg_op_name_len Its refcnt is incremented when a wizard with op_info => NAME is created, and decremented in the destructor of those wizards. This fixes segfaults that happen when magic with op_info => NAME is casted onto a stash and not dispelled before END time. --- diff --git a/Magic.xs b/Magic.xs index 7089937..d9eab57 100644 --- a/Magic.xs +++ b/Magic.xs @@ -498,7 +498,8 @@ STATIC UV vmg_dispell(pTHX_ SV *sv, U16 sig) { #define VMG_OP_INFO_NAME 1 #define VMG_OP_INFO_OBJECT 2 -STATIC STRLEN *vmg_op_name_len = NULL; +STATIC U32 vmg_op_name_refcnt = 0; +STATIC STRLEN *vmg_op_name_len = NULL; STATIC HV *vmg_b__op_stash = NULL; @@ -512,6 +513,7 @@ STATIC void vmg_op_info_init(pTHX_ unsigned int opinfo) { for (t = 0; t < OP_max; ++t) vmg_op_name_len[t] = strlen(PL_op_name[t]); } + ++vmg_op_name_refcnt; break; case VMG_OP_INFO_OBJECT: if (!vmg_b__op_stash) { @@ -524,6 +526,22 @@ STATIC void vmg_op_info_init(pTHX_ unsigned int opinfo) { } } +STATIC void vmg_op_info_deinit(unsigned int opinfo) { + switch (opinfo) { + case VMG_OP_INFO_NAME: + if (vmg_op_name_refcnt > 0) + --vmg_op_name_refcnt; + if (!vmg_op_name_refcnt && vmg_op_name_len) { + Safefree(vmg_op_name_len); + vmg_op_name_len = NULL; + } + break; + case VMG_OP_INFO_OBJECT: + default: + break; + } +} + STATIC SV *vmg_op_info(pTHX_ unsigned int opinfo) { #define vmg_op_info(W) vmg_op_info(aTHX_ (W)) if (!PL_op) @@ -877,6 +895,9 @@ STATIC int vmg_wizard_free(pTHX_ SV *wiz, MAGIC *mg) { if (w->cb_delete != NULL) { SvREFCNT_dec(SvRV(w->cb_delete)); } #endif /* VMG_UVAR */ + if (w->opinfo) + vmg_op_info_deinit(w->opinfo); + Safefree(w->vtbl); Safefree(w); @@ -1269,13 +1290,3 @@ CODE: RETVAL = newSVuv(vmg_dispell(SvRV(sv), sig)); OUTPUT: RETVAL - -void -_cleanup() -PROTOTYPE: -PPCODE: - if (vmg_op_name_len) { - Safefree(vmg_op_name_len); - vmg_op_name_len = NULL; - } - XSRETURN(0); diff --git a/lib/Variable/Magic.pm b/lib/Variable/Magic.pm index 00c86ba..4456efb 100644 --- a/lib/Variable/Magic.pm +++ b/lib/Variable/Magic.pm @@ -479,8 +479,6 @@ our %EXPORT_TAGS = ( our @EXPORT_OK = map { @$_ } values %EXPORT_TAGS; $EXPORT_TAGS{'all'} = [ @EXPORT_OK ]; -END { _cleanup() } - =head1 CAVEATS If you store a magic object in the private data slot, the magic won't be accessible by L since it's not copied by assignation.