From: Vincent Pit Date: Mon, 30 Mar 2015 20:45:56 +0000 (-0300) Subject: Revamp the setup boot logic X-Git-Tag: v0.57~16 X-Git-Url: http://git.vpit.fr/?p=perl%2Fmodules%2FVariable-Magic.git;a=commitdiff_plain;h=efaaf15b83e17a4417730161f3c1b0e9398458ac Revamp the setup boot logic All of this just to fix a couple of leaks! --- diff --git a/Magic.xs b/Magic.xs index 44d4c89..55ca968 100644 --- a/Magic.xs +++ b/Magic.xs @@ -1740,57 +1740,138 @@ static I32 vmg_svt_val(pTHX_ IV action, SV *sv) { #endif /* VMG_UVAR */ -/* --- Macros for the XS section ------------------------------------------- */ +/* --- Global setup/teardown ----------------------------------------------- */ -#ifdef CvISXSUB -# define VMG_CVOK(C) \ - ((CvISXSUB(C) ? (void *) CvXSUB(C) : (void *) CvROOT(C)) ? 1 : 0) -#else -# define VMG_CVOK(C) (CvROOT(C) || CvXSUB(C)) +static U32 vmg_initialized = 0; + +static void vmg_global_teardown_late(pTHX) { +#define vmg_global_teardown_late() vmg_global_teardown_late(aTHX) +#if VMG_THREADSAFE + MUTEX_DESTROY(&vmg_op_name_init_mutex); + MUTEX_DESTROY(&vmg_vtable_refcount_mutex); #endif -#define VMG_CBOK(S) ((SvTYPE(S) == SVt_PVCV) ? VMG_CVOK(S) : SvOK(S)) + vmg_initialized = 0; -#define VMG_SET_CB(S, N) { \ - SV *cb = (S); \ - if (SvOK(cb) && SvROK(cb)) { \ - cb = SvRV(cb); \ - if (VMG_CBOK(cb)) \ - SvREFCNT_inc_simple_void(cb); \ - else \ - cb = NULL; \ - } else { \ - cb = NULL; \ - } \ - w->cb_ ## N = cb; \ + return; } -#define VMG_SET_SVT_CB(S, N) { \ - SV *cb = (S); \ - if (SvOK(cb) && SvROK(cb)) { \ - cb = SvRV(cb); \ - if (VMG_CBOK(cb)) { \ - t->svt_ ## N = vmg_svt_ ## N; \ - SvREFCNT_inc_simple_void(cb); \ - } else { \ - t->svt_ ## N = vmg_svt_ ## N ## _noop; \ - cb = NULL; \ - } \ - } else { \ - t->svt_ ## N = NULL; \ - cb = NULL; \ - } \ - w->cb_ ## N = cb; \ +static int vmg_global_teardown_free(pTHX_ SV *sv, MAGIC *mg) { + vmg_global_teardown_late(); + + return 0; } -/* --- XS ------------------------------------------------------------------ */ +static MGVTBL vmg_global_teardown_vtbl = { + 0, + 0, + 0, + 0, + vmg_global_teardown_free +#if MGf_COPY + , 0 +#endif +#if MGf_DUP + , 0 +#endif +#if MGf_LOCAL + , 0 +#endif +}; -MODULE = Variable::Magic PACKAGE = Variable::Magic +static signed char vmg_destruct_level(pTHX) { +#define vmg_destruct_level() vmg_destruct_level(aTHX) + signed char lvl; -PROTOTYPES: ENABLE + lvl = PL_perl_destruct_level; -BOOT: -{ +#ifdef DEBUGGING + { + const char *s = PerlEnv_getenv("PERL_DESTRUCT_LEVEL"); + if (s) { + int i; +#if VMG_HAS_PERL(5, 21, 3) + if (strEQ(s, "-1")) { + i = -1; + } else { +# if VMG_HAS_PERL(5, 21, 10) + UV uv; + if (Perl_grok_atoUV(s, &uv, NULL) && uv <= INT_MAX) + i = (int) uv; + else + i = 0; +# else /* VMG_HAS_PERL(5, 21, 3) && !VMG_HAS_PERL(5, 21, 10) */ + i = Perl_grok_atou(s, NULL); +# endif + } +#else /* !VMG_HAS_PERL(5, 21, 3) */ + i = atoi(s); +#endif + if (lvl < i) + lvl = i; + } + } +#endif + + return lvl; +} + +static void vmg_global_teardown(pTHX_ void *root) { + if (!vmg_initialized) + return; + +#if VMG_MULTIPLICITY + if (aTHX != root) + return; +#endif + + if (vmg_destruct_level() == 0) { + vmg_global_teardown_late(); + } else { + if (!PL_strtab) + PL_strtab = newHV(); + vmg_sv_magicext((SV *) PL_strtab, NULL, &vmg_global_teardown_vtbl, NULL, 0); + } + + return; +} + +static void vmg_global_setup(pTHX) { +#define vmg_global_setup() vmg_global_setup(aTHX) + if (vmg_initialized) + return; + +#if VMG_THREADSAFE + MUTEX_INIT(&vmg_vtable_refcount_mutex); + MUTEX_INIT(&vmg_op_name_init_mutex); +#endif + +#if VMG_MULTIPLICITY + call_atexit(vmg_global_teardown, aTHX); +#else + call_atexit(vmg_global_teardown, NULL); +#endif + + vmg_initialized = 1; + + return; +} + +/* --- Interpreter setup/teardown ------------------------------------------ */ + +static void vmg_local_teardown(pTHX_ void *param) { + dMY_CXT; + + if (MY_CXT.depth == 0 && MY_CXT.freed_tokens) { + vmg_magic_chain_free(MY_CXT.freed_tokens, NULL); + MY_CXT.freed_tokens = NULL; + } + + return; +} + +static void vmg_local_setup(pTHX) { +#define vmg_local_setup() vmg_local_setup(aTHX) HV *stash; int c; @@ -1801,7 +1882,6 @@ BOOT: MY_CXT.depth = 0; MY_CXT.freed_tokens = NULL; - /* XS doesn't like a blank line here */ #if VMG_PROPAGATE_ERRSV_NEEDS_TRAMPOLINE vmg_trampoline_init(&MY_CXT.propagate_errsv, vmg_pp_propagate_errsv); #endif @@ -1809,12 +1889,6 @@ BOOT: vmg_trampoline_init(&MY_CXT.reset_rmg, vmg_pp_reset_rmg); #endif - /* XS doesn't like a blank line here */ -#if VMG_THREADSAFE - MUTEX_INIT(&vmg_vtable_refcount_mutex); - MUTEX_INIT(&vmg_op_name_init_mutex); -#endif - stash = gv_stashpv(__PACKAGE__, 1); newCONSTSUB(stash, "MGf_COPY", newSVuv(MGf_COPY)); newCONSTSUB(stash, "MGf_DUP", newSVuv(MGf_DUP)); @@ -1842,6 +1916,65 @@ BOOT: newCONSTSUB(stash, "VMG_FORKSAFE", newSVuv(VMG_FORKSAFE)); newCONSTSUB(stash, "VMG_OP_INFO_NAME", newSVuv(VMG_OP_INFO_NAME)); newCONSTSUB(stash, "VMG_OP_INFO_OBJECT", newSVuv(VMG_OP_INFO_OBJECT)); + + call_atexit(vmg_local_teardown, NULL); + + return; +} + +/* --- Macros for the XS section ------------------------------------------- */ + +#ifdef CvISXSUB +# define VMG_CVOK(C) \ + ((CvISXSUB(C) ? (void *) CvXSUB(C) : (void *) CvROOT(C)) ? 1 : 0) +#else +# define VMG_CVOK(C) (CvROOT(C) || CvXSUB(C)) +#endif + +#define VMG_CBOK(S) ((SvTYPE(S) == SVt_PVCV) ? VMG_CVOK(S) : SvOK(S)) + +#define VMG_SET_CB(S, N) { \ + SV *cb = (S); \ + if (SvOK(cb) && SvROK(cb)) { \ + cb = SvRV(cb); \ + if (VMG_CBOK(cb)) \ + SvREFCNT_inc_simple_void(cb); \ + else \ + cb = NULL; \ + } else { \ + cb = NULL; \ + } \ + w->cb_ ## N = cb; \ +} + +#define VMG_SET_SVT_CB(S, N) { \ + SV *cb = (S); \ + if (SvOK(cb) && SvROK(cb)) { \ + cb = SvRV(cb); \ + if (VMG_CBOK(cb)) { \ + t->svt_ ## N = vmg_svt_ ## N; \ + SvREFCNT_inc_simple_void(cb); \ + } else { \ + t->svt_ ## N = vmg_svt_ ## N ## _noop; \ + cb = NULL; \ + } \ + } else { \ + t->svt_ ## N = NULL; \ + cb = NULL; \ + } \ + w->cb_ ## N = cb; \ +} + +/* --- XS ------------------------------------------------------------------ */ + +MODULE = Variable::Magic PACKAGE = Variable::Magic + +PROTOTYPES: ENABLE + +BOOT: +{ + vmg_global_setup(); + vmg_local_setup(); } #if VMG_THREADSAFE