X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;f=Magic.xs;h=1dada023c031867f619d812dc50bdc76facc7a78;hb=1ff75d21f8a370b6533873480725f78eebd70efc;hp=0bd0bfd2ba1d45668266d373b0d04f0c4f884abd;hpb=a373cfef20bb5e4c99ba384ba650b36431908ade;p=perl%2Fmodules%2FVariable-Magic.git diff --git a/Magic.xs b/Magic.xs index 0bd0bfd..1dada02 100644 --- a/Magic.xs +++ b/Magic.xs @@ -36,6 +36,11 @@ # define dNOOP #endif +/* Safe unless stated otherwise in Makefile.PL */ +#ifndef VMG_FORKSAFE +# define VMG_FORKSAFE 1 +#endif + #ifndef VMG_MULTIPLICITY # if defined(MULTIPLICITY) || defined(PERL_IMPLICIT_CONTEXT) # define VMG_MULTIPLICITY 1 @@ -135,8 +140,9 @@ STATIC SV *vmg_clone(pTHX_ SV *sv, tTHX owner) { # endif #endif -/* uvar magic and Hash::Util::FieldHash were commited with 28419 */ -#if VMG_HAS_PERL_MAINT(5, 9, 4, 28419) || VMG_HAS_PERL(5, 10, 0) +/* uvar magic and Hash::Util::FieldHash were commited with 28419, but only + * enable it on 5.10 */ +#if VMG_HAS_PERL(5, 10, 0) # define VMG_UVAR 1 #else # define VMG_UVAR 0 @@ -812,6 +818,10 @@ STATIC int vmg_svt_clear(pTHX_ SV *sv, MAGIC *mg) { STATIC int vmg_svt_free(pTHX_ SV *sv, MAGIC *mg) { const MGWIZ *w; +#if VMG_HAS_PERL(5, 9, 5) + PERL_CONTEXT saved_cx; + I32 cxix; +#endif unsigned int had_err, has_err, flags = G_SCALAR | G_EVAL; int ret = 0; @@ -849,8 +859,23 @@ STATIC int vmg_svt_free(pTHX_ SV *sv, MAGIC *mg) { if (had_err) flags |= G_KEEPERR; +#if VMG_HAS_PERL(5, 9, 5) + /* This context should not be used anymore, but since we croak in places the + * core doesn't even dare to, some pointers to it may remain in the upper call + * stack. Make sure call_sv() doesn't clobber it. */ + if (cxstack_ix < cxstack_max) + cxix = cxstack_ix + 1; + else + cxix = Perl_cxinc(aTHX); + saved_cx = cxstack[cxix]; +#endif + call_sv(w->cb_free, flags); +#if VMG_HAS_PERL(5, 9, 5) + cxstack[cxix] = saved_cx; +#endif + has_err = SvTRUE(ERRSV); if (IN_PERL_COMPILETIME && !had_err && has_err) ++PL_error_count; @@ -860,15 +885,6 @@ STATIC int vmg_svt_free(pTHX_ SV *sv, MAGIC *mg) { FREETMPS; LEAVE; - if (has_err) { - /* Get the eval context that was pushed by call_sv, and fake an entry for the - * namesv, as die_where will need it to be non NULL later */ - PERL_CONTEXT *cx = cxstack + cxstack_ix + 1; - if (!cx->blk_eval.old_namesv) - cx->blk_eval.old_namesv - = sv_2mortal(newSVpvn_share("Variable/Magic/DUMMY.pm", 23, 0)); - } - /* Calling SvREFCNT_dec() will trigger destructors in an infinite loop, so * we have to rely on SvREFCNT() being a lvalue. Heck, even the core does it */ --SvREFCNT(sv); @@ -1028,8 +1044,16 @@ STATIC int vmg_wizard_free(pTHX_ SV *wiz, MAGIC *mg) { if (hv_delete(MY_CXT.wizards, buf, sprintf(buf, "%u", w->sig), 0) != wiz) return 0; } - SvFLAGS(wiz) |= SVf_BREAK; - FREETMPS; + + /* Unmortalize the wizard to avoid it being freed in weird places. */ + if (SvTEMP(wiz) && !SvREFCNT(wiz)) { + const I32 myfloor = PL_tmps_floor; + I32 i; + for (i = PL_tmps_ix; i > myfloor; --i) { + if (PL_tmps_stack[i] == wiz) + PL_tmps_stack[i] = NULL; + } + } if (w->cb_data) SvREFCNT_dec(SvRV(w->cb_data)); if (w->cb_get) SvREFCNT_dec(SvRV(w->cb_get)); @@ -1244,6 +1268,7 @@ BOOT: newSVuv(VMG_COMPAT_SCALAR_LENGTH_NOLEN)); newCONSTSUB(stash, "VMG_PERL_PATCHLEVEL", newSVuv(VMG_PERL_PATCHLEVEL)); newCONSTSUB(stash, "VMG_THREADSAFE", newSVuv(VMG_THREADSAFE)); + 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)); } @@ -1449,7 +1474,7 @@ PPCODE: sig = vmg_wizard_sig(wiz); data = vmg_data_get(SvRV(sv), sig); if (!data) - XSRETURN_UNDEF; + XSRETURN_EMPTY; ST(0) = data; XSRETURN(1);