X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/7636ea95c57762930accf4358f7c0c2dec086b5e..ce2077b184ce12e83580ca1d9686e4af75dc538a:/mg.c?ds=sidebyside
diff --git a/mg.c b/mg.c
index 0341f6e..fa4b446 100644
--- a/mg.c
+++ b/mg.c
@@ -84,6 +84,7 @@ struct magic_state {
I32 mgs_ss_ix;
U32 mgs_magical;
bool mgs_readonly;
+ bool mgs_bumped;
};
/* MGS is typedef'ed to struct magic_state in perl.h */
@@ -92,9 +93,21 @@ S_save_magic(pTHX_ I32 mgs_ix, SV *sv)
{
dVAR;
MGS* mgs;
+ bool bumped = FALSE;
PERL_ARGS_ASSERT_SAVE_MAGIC;
+ /* we shouldn't really be called here with RC==0, but it can sometimes
+ * happen via mg_clear() (which also shouldn't be called when RC==0,
+ * but it can happen). Handle this case gracefully(ish) by not RC++
+ * and thus avoiding the resultant double free */
+ if (SvREFCNT(sv) > 0) {
+ /* guard against sv getting freed midway through the mg clearing,
+ * by holding a private reference for the duration. */
+ SvREFCNT_inc_simple_void_NN(sv);
+ bumped = TRUE;
+ }
+
assert(SvMAGICAL(sv));
/* Turning READONLY off for a copy-on-write scalar (including shared
hash keys) is a bad idea. */
@@ -108,6 +121,7 @@ S_save_magic(pTHX_ I32 mgs_ix, SV *sv)
mgs->mgs_magical = SvMAGICAL(sv);
mgs->mgs_readonly = SvREADONLY(sv) != 0;
mgs->mgs_ss_ix = PL_savestack_ix; /* points after the saved destructor */
+ mgs->mgs_bumped = bumped;
SvMAGICAL_off(sv);
SvREADONLY_off(sv);
@@ -150,40 +164,6 @@ Perl_mg_magical(pTHX_ SV *sv)
}
}
-
-/* is this container magic (%ENV, $1 etc), or value magic (pos, taint etc)? */
-
-STATIC bool
-S_is_container_magic(const MAGIC *mg)
-{
- assert(mg);
- switch (mg->mg_type) {
- case PERL_MAGIC_bm:
- case PERL_MAGIC_fm:
- case PERL_MAGIC_regex_global:
- case PERL_MAGIC_nkeys:
-#ifdef USE_LOCALE_COLLATE
- case PERL_MAGIC_collxfrm:
-#endif
- case PERL_MAGIC_qr:
- case PERL_MAGIC_taint:
- case PERL_MAGIC_vec:
- case PERL_MAGIC_vstring:
- case PERL_MAGIC_utf8:
- case PERL_MAGIC_substr:
- case PERL_MAGIC_defelem:
- case PERL_MAGIC_arylen:
- case PERL_MAGIC_pos:
- case PERL_MAGIC_backref:
- case PERL_MAGIC_arylen_p:
- case PERL_MAGIC_rhash:
- case PERL_MAGIC_symtab:
- return 0;
- default:
- return 1;
- }
-}
-
/*
=for apidoc mg_get
@@ -197,23 +177,11 @@ Perl_mg_get(pTHX_ SV *sv)
{
dVAR;
const I32 mgs_ix = SSNEW(sizeof(MGS));
- const bool was_temp = cBOOL(SvTEMP(sv));
bool have_new = 0;
MAGIC *newmg, *head, *cur, *mg;
- /* guard against sv having being freed midway by holding a private
- reference. */
PERL_ARGS_ASSERT_MG_GET;
- /* sv_2mortal has this side effect of turning on the TEMP flag, which can
- cause the SV's buffer to get stolen (and maybe other stuff).
- So restore it.
- */
- sv_2mortal(SvREFCNT_inc_simple_NN(sv));
- if (!was_temp) {
- SvTEMP_off(sv);
- }
-
save_magic(mgs_ix, sv);
/* We must call svt_get(sv, mg) for each valid entry in the linked
@@ -226,7 +194,7 @@ Perl_mg_get(pTHX_ SV *sv)
MAGIC * const nextmg = mg->mg_moremagic; /* it may delete itself */
if (!(mg->mg_flags & MGf_GSKIP) && vtbl && vtbl->svt_get) {
- CALL_FPTR(vtbl->svt_get)(aTHX_ sv, mg);
+ vtbl->svt_get(aTHX_ sv, mg);
/* guard against magic having been deleted - eg FETCH calling
* untie */
@@ -262,12 +230,6 @@ Perl_mg_get(pTHX_ SV *sv)
}
restore_magic(INT2PTR(void *, (IV)mgs_ix));
-
- if (SvREFCNT(sv) == 1) {
- /* We hold the last reference to this SV, which implies that the
- SV was deleted as a side effect of the routines we called. */
- SvOK_off(sv);
- }
return 0;
}
@@ -298,10 +260,11 @@ Perl_mg_set(pTHX_ SV *sv)
mg->mg_flags &= ~MGf_GSKIP; /* setting requires another read */
(SSPTR(mgs_ix, MGS*))->mgs_magical = 0;
}
- if (PL_localizing == 2 && !S_is_container_magic(mg))
+ if (PL_localizing == 2
+ && (PERL_MAGIC_TYPE_IS_VALUE_MAGIC(mg->mg_type) || sv == DEFSV))
continue;
if (vtbl && vtbl->svt_set)
- CALL_FPTR(vtbl->svt_set)(aTHX_ sv, mg);
+ vtbl->svt_set(aTHX_ sv, mg);
}
restore_magic(INT2PTR(void*, (IV)mgs_ix));
@@ -331,7 +294,7 @@ Perl_mg_length(pTHX_ SV *sv)
const I32 mgs_ix = SSNEW(sizeof(MGS));
save_magic(mgs_ix, sv);
/* omit MGf_GSKIP -- not changed here */
- len = CALL_FPTR(vtbl->svt_len)(aTHX_ sv, mg);
+ len = vtbl->svt_len(aTHX_ sv, mg);
restore_magic(INT2PTR(void*, (IV)mgs_ix));
return len;
}
@@ -363,7 +326,7 @@ Perl_mg_size(pTHX_ SV *sv)
I32 len;
save_magic(mgs_ix, sv);
/* omit MGf_GSKIP -- not changed here */
- len = CALL_FPTR(vtbl->svt_len)(aTHX_ sv, mg);
+ len = vtbl->svt_len(aTHX_ sv, mg);
restore_magic(INT2PTR(void*, (IV)mgs_ix));
return len;
}
@@ -407,13 +370,33 @@ Perl_mg_clear(pTHX_ SV *sv)
nextmg = mg->mg_moremagic; /* it may delete itself */
if (vtbl && vtbl->svt_clear)
- CALL_FPTR(vtbl->svt_clear)(aTHX_ sv, mg);
+ vtbl->svt_clear(aTHX_ sv, mg);
}
restore_magic(INT2PTR(void*, (IV)mgs_ix));
return 0;
}
+static MAGIC*
+S_mg_findext_flags(pTHX_ const SV *sv, int type, const MGVTBL *vtbl, U32 flags)
+{
+ PERL_UNUSED_CONTEXT;
+
+ assert(flags <= 1);
+
+ if (sv) {
+ MAGIC *mg;
+
+ for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
+ if (mg->mg_type == type && (!flags || mg->mg_virtual == vtbl)) {
+ return mg;
+ }
+ }
+ }
+
+ return NULL;
+}
+
/*
=for apidoc mg_find
@@ -425,15 +408,22 @@ Finds the magic pointer for type matching the SV. See C.
MAGIC*
Perl_mg_find(pTHX_ const SV *sv, int type)
{
- PERL_UNUSED_CONTEXT;
- if (sv) {
- MAGIC *mg;
- for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
- if (mg->mg_type == type)
- return mg;
- }
- }
- return NULL;
+ return S_mg_findext_flags(aTHX_ sv, type, NULL, 0);
+}
+
+/*
+=for apidoc mg_findext
+
+Finds the magic pointer of C with the given C for the C. See
+C.
+
+=cut
+*/
+
+MAGIC*
+Perl_mg_findext(pTHX_ const SV *sv, int type, const MGVTBL *vtbl)
+{
+ return S_mg_findext_flags(aTHX_ sv, type, vtbl, 1);
}
/*
@@ -455,7 +445,7 @@ Perl_mg_copy(pTHX_ SV *sv, SV *nsv, const char *key, I32 klen)
for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
const MGVTBL* const vtbl = mg->mg_virtual;
if ((mg->mg_flags & MGf_COPY) && vtbl->svt_copy){
- count += CALL_FPTR(vtbl->svt_copy)(aTHX_ sv, mg, nsv, key, klen);
+ count += vtbl->svt_copy(aTHX_ sv, mg, nsv, key, klen);
}
else {
const char type = mg->mg_type;
@@ -496,19 +486,22 @@ Perl_mg_localize(pTHX_ SV *sv, SV *nsv, bool setmagic)
PERL_ARGS_ASSERT_MG_LOCALIZE;
+ if (nsv == DEFSV)
+ return;
+
for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
const MGVTBL* const vtbl = mg->mg_virtual;
- if (!S_is_container_magic(mg))
+ if (PERL_MAGIC_TYPE_IS_VALUE_MAGIC(mg->mg_type))
continue;
if ((mg->mg_flags & MGf_LOCAL) && vtbl->svt_local)
- (void)CALL_FPTR(vtbl->svt_local)(aTHX_ nsv, mg);
+ (void)vtbl->svt_local(aTHX_ nsv, mg);
else
sv_magicext(nsv, mg->mg_obj, mg->mg_type, vtbl,
mg->mg_ptr, mg->mg_len);
/* container types should remain read-only across localization */
- SvFLAGS(nsv) |= SvREADONLY(sv);
+ if (!SvIsCOW(sv)) SvFLAGS(nsv) |= SvREADONLY(sv);
}
if (SvTYPE(nsv) >= SVt_PVMG && SvMAGIC(nsv)) {
@@ -521,6 +514,24 @@ Perl_mg_localize(pTHX_ SV *sv, SV *nsv, bool setmagic)
}
}
+#define mg_free_struct(sv, mg) S_mg_free_struct(aTHX_ sv, mg)
+static void
+S_mg_free_struct(pTHX_ SV *sv, MAGIC *mg)
+{
+ const MGVTBL* const vtbl = mg->mg_virtual;
+ if (vtbl && vtbl->svt_free)
+ vtbl->svt_free(aTHX_ sv, mg);
+ if (mg->mg_ptr && mg->mg_type != PERL_MAGIC_regex_global) {
+ if (mg->mg_len > 0 || mg->mg_type == PERL_MAGIC_utf8)
+ Safefree(mg->mg_ptr);
+ else if (mg->mg_len == HEf_SVKEY)
+ SvREFCNT_dec(MUTABLE_SV(mg->mg_ptr));
+ }
+ if (mg->mg_flags & MGf_REFCOUNTED)
+ SvREFCNT_dec(mg->mg_obj);
+ Safefree(mg);
+}
+
/*
=for apidoc mg_free
@@ -538,19 +549,8 @@ Perl_mg_free(pTHX_ SV *sv)
PERL_ARGS_ASSERT_MG_FREE;
for (mg = SvMAGIC(sv); mg; mg = moremagic) {
- const MGVTBL* const vtbl = mg->mg_virtual;
moremagic = mg->mg_moremagic;
- if (vtbl && vtbl->svt_free)
- CALL_FPTR(vtbl->svt_free)(aTHX_ sv, mg);
- if (mg->mg_ptr && mg->mg_type != PERL_MAGIC_regex_global) {
- if (mg->mg_len > 0 || mg->mg_type == PERL_MAGIC_utf8)
- Safefree(mg->mg_ptr);
- else if (mg->mg_len == HEf_SVKEY)
- SvREFCNT_dec(MUTABLE_SV(mg->mg_ptr));
- }
- if (mg->mg_flags & MGf_REFCOUNTED)
- SvREFCNT_dec(mg->mg_obj);
- Safefree(mg);
+ mg_free_struct(sv, mg);
SvMAGIC_set(sv, moremagic);
}
SvMAGIC_set(sv, NULL);
@@ -558,6 +558,39 @@ Perl_mg_free(pTHX_ SV *sv)
return 0;
}
+/*
+=for apidoc Am|void|mg_free_type|SV *sv|int how
+
+Remove any magic of type I from the SV I. See L.
+
+=cut
+*/
+
+void
+Perl_mg_free_type(pTHX_ SV *sv, int how)
+{
+ MAGIC *mg, *prevmg, *moremg;
+ PERL_ARGS_ASSERT_MG_FREE_TYPE;
+ for (prevmg = NULL, mg = SvMAGIC(sv); mg; prevmg = mg, mg = moremg) {
+ MAGIC *newhead;
+ moremg = mg->mg_moremagic;
+ if (mg->mg_type == how) {
+ /* temporarily move to the head of the magic chain, in case
+ custom free code relies on this historical aspect of mg_free */
+ if (prevmg) {
+ prevmg->mg_moremagic = moremg;
+ mg->mg_moremagic = SvMAGIC(sv);
+ SvMAGIC_set(sv, mg);
+ }
+ newhead = mg->mg_moremagic;
+ mg_free_struct(sv, mg);
+ SvMAGIC_set(sv, newhead);
+ mg = prevmg;
+ }
+ }
+ mg_magical(sv);
+}
+
#include
U32
@@ -634,7 +667,7 @@ Perl_magic_regdatum_set(pTHX_ SV *sv, MAGIC *mg)
PERL_ARGS_ASSERT_MAGIC_REGDATUM_SET;
PERL_UNUSED_ARG(sv);
PERL_UNUSED_ARG(mg);
- Perl_croak(aTHX_ "%s", PL_no_modify);
+ Perl_croak_no_modify(aTHX);
NORETURN_FUNCTION_END;
}
@@ -739,17 +772,13 @@ Perl_emulate_cop_io(pTHX_ const COP *const c, SV *const sv)
sv_setpvs(sv, "");
SvUTF8_off(sv);
if ((CopHINTS_get(c) & HINT_LEXICAL_IO_IN)) {
- SV *const value = Perl_refcounted_he_fetch(aTHX_
- c->cop_hints_hash,
- 0, "open<", 5, 0, 0);
+ SV *const value = cop_hints_fetch_pvs(c, "open<", 0);
assert(value);
sv_catsv(sv, value);
}
sv_catpvs(sv, "\0");
if ((CopHINTS_get(c) & HINT_LEXICAL_IO_OUT)) {
- SV *const value = Perl_refcounted_he_fetch(aTHX_
- c->cop_hints_hash,
- 0, "open>", 5, 0, 0);
+ SV *const value = cop_hints_fetch_pvs(c, "open>", 0);
assert(value);
sv_catsv(sv, value);
}
@@ -761,7 +790,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
{
dVAR;
register I32 paren;
- register char *s = NULL;
+ register const char *s = NULL;
register REGEXP *rx;
const char * const remaining = mg->mg_ptr + 1;
const char nextchar = *remaining;
@@ -771,6 +800,8 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
switch (*mg->mg_ptr) {
case '\001': /* ^A */
sv_setsv(sv, PL_bodytarget);
+ if (SvTAINTED(PL_bodytarget))
+ SvTAINTED_on(sv);
break;
case '\003': /* ^C, ^CHILD_ERROR_NATIVE */
if (nextchar == '\0') {
@@ -839,6 +870,12 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
case '\006': /* ^F */
sv_setiv(sv, (IV)PL_maxsysfd);
break;
+ case '\007': /* ^GLOBAL_PHASE */
+ if (strEQ(remaining, "LOBAL_PHASE")) {
+ sv_setpvn(sv, PL_phase_names[PL_phase],
+ strlen(PL_phase_names[PL_phase]));
+ }
+ break;
case '\010': /* ^H */
sv_setiv(sv, (IV)PL_hints);
break;
@@ -854,7 +891,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
Perl_emulate_cop_io(aTHX_ &PL_compiling, sv);
}
break;
- case '\020':
+ case '\020':
if (nextchar == '\0') { /* ^P */
sv_setiv(sv, (IV)PL_perldb);
} else if (strEQ(remaining, "REMATCH")) { /* $^PREMATCH */
@@ -995,9 +1032,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
}
break;
case '^':
- if (!isGV_with_GP(PL_defoutgv))
- s = "";
- else if (GvIOp(PL_defoutgv))
+ if (GvIOp(PL_defoutgv))
s = IoTOP_NAME(GvIOp(PL_defoutgv));
if (s)
sv_setpv(sv,s);
@@ -1007,9 +1042,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
}
break;
case '~':
- if (!isGV_with_GP(PL_defoutgv))
- s = "";
- else if (GvIOp(PL_defoutgv))
+ if (GvIOp(PL_defoutgv))
s = IoFMT_NAME(GvIOp(PL_defoutgv));
if (!s)
s = GvENAME(PL_defoutgv);
@@ -1032,7 +1065,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
case '/':
break;
case '[':
- sv_setiv(sv, (IV)CopARYBASE_get(PL_curcop));
+ sv_setiv(sv, 0);
break;
case '|':
if (GvIO(PL_defoutgv))
@@ -1042,6 +1075,16 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
if (PL_ors_sv)
sv_copypv(sv, PL_ors_sv);
break;
+ case '$': /* $$ */
+ {
+ IV const pid = (IV)PerlProc_getpid();
+ if (isGV(mg->mg_obj) || SvIV(mg->mg_obj) != pid)
+ /* never set manually, or at least not since last fork */
+ sv_setiv(sv, pid);
+ /* else a value has been assigned manually, so do nothing */
+ }
+ break;
+
case '!':
{
dSAVE_ERRNO;
@@ -1136,7 +1179,6 @@ Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg)
#ifdef VMS
if (s && klen == 8 && strEQ(ptr, "DCL$PATH")) {
char pathbuf[256], eltbuf[256], *cp, *elt;
- Stat_t sbuf;
int i = 0, j = 0;
my_strlcpy(eltbuf, s, sizeof(eltbuf));
@@ -1260,7 +1302,9 @@ Perl_magic_getsig(pTHX_ SV *sv, MAGIC *mg)
PERL_ARGS_ASSERT_MAGIC_GETSIG;
if (!i) {
- mg->mg_private = i = whichsig(MgPV_nolen_const(mg));
+ STRLEN siglen;
+ const char * sig = MgPV_const(mg, siglen);
+ mg->mg_private = i = whichsig_pvn(sig, siglen);
}
if (i > 0) {
@@ -1291,7 +1335,6 @@ int
Perl_magic_clearsig(pTHX_ SV *sv, MAGIC *mg)
{
PERL_ARGS_ASSERT_MAGIC_CLEARSIG;
- PERL_UNUSED_ARG(sv);
magic_setsig(NULL, mg);
return sv_unmagic(sv, mg->mg_type);
@@ -1376,6 +1419,14 @@ Perl_csighandler_init(void)
}
#endif
+#if defined HAS_SIGPROCMASK
+static void
+unblock_sigmask(pTHX_ void* newset)
+{
+ sigprocmask(SIG_UNBLOCK, (sigset_t*)newset, NULL);
+}
+#endif
+
void
Perl_despatch_signals(pTHX)
{
@@ -1384,15 +1435,40 @@ Perl_despatch_signals(pTHX)
PL_sig_pending = 0;
for (sig = 1; sig < SIG_SIZE; sig++) {
if (PL_psig_pend[sig]) {
- PERL_BLOCKSIG_ADD(set, sig);
+ dSAVE_ERRNO;
+#ifdef HAS_SIGPROCMASK
+ /* From sigaction(2) (FreeBSD man page):
+ * | Signal routines normally execute with the signal that
+ * | caused their invocation blocked, but other signals may
+ * | yet occur.
+ * Emulation of this behavior (from within Perl) is enabled
+ * using sigprocmask
+ */
+ int was_blocked;
+ sigset_t newset, oldset;
+
+ sigemptyset(&newset);
+ sigaddset(&newset, sig);
+ sigprocmask(SIG_BLOCK, &newset, &oldset);
+ was_blocked = sigismember(&oldset, sig);
+ if (!was_blocked) {
+ SV* save_sv = newSVpvn((char *)(&newset), sizeof(sigset_t));
+ ENTER;
+ SAVEFREESV(save_sv);
+ SAVEDESTRUCTOR_X(unblock_sigmask, SvPV_nolen(save_sv));
+ }
+#endif
PL_psig_pend[sig] = 0;
- PERL_BLOCKSIG_BLOCK(set);
#if defined(HAS_SIGACTION) && defined(SA_SIGINFO)
(*PL_sighandlerp)(sig, NULL, NULL);
#else
(*PL_sighandlerp)(sig);
#endif
- PERL_BLOCKSIG_UNBLOCK(set);
+#ifdef HAS_SIGPROCMASK
+ if (!was_blocked)
+ LEAVE;
+#endif
+ RESTORE_ERRNO;
}
}
}
@@ -1419,9 +1495,9 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
PERL_ARGS_ASSERT_MAGIC_SETSIG;
if (*s == '_') {
- if (strEQ(s,"__DIE__"))
+ if (memEQs(s, len, "__DIE__"))
svp = &PL_diehook;
- else if (strEQ(s,"__WARN__")
+ else if (memEQs(s, len, "__WARN__")
&& (sv ? 1 : PL_warnhook != PERL_WARNHOOK_FATAL)) {
/* Merge the existing behaviours, which are as follows:
magic_setsig, we always set svp to &PL_warnhook
@@ -1429,8 +1505,11 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
For magic_clearsig, we don't change the warnings handler if it's
set to the &PL_warnhook. */
svp = &PL_warnhook;
- } else if (sv)
- Perl_croak(aTHX_ "No such hook: %s", s);
+ } else if (sv) {
+ SV *tmp = sv_newmortal();
+ Perl_croak(aTHX_ "No such hook: %s",
+ pv_pretty(tmp, s, len, 0, NULL, NULL, 0));
+ }
i = 0;
if (svp && *svp) {
if (*svp != PERL_WARNHOOK_FATAL)
@@ -1441,12 +1520,15 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
else {
i = (I16)mg->mg_private;
if (!i) {
- i = whichsig(s); /* ...no, a brick */
+ i = whichsig_pvn(s, len); /* ...no, a brick */
mg->mg_private = (U16)i;
}
if (i <= 0) {
- if (sv)
- Perl_ck_warner(aTHX_ packWARN(WARN_SIGNAL), "No such signal: SIG%s", s);
+ if (sv) {
+ SV *tmp = sv_newmortal();
+ Perl_ck_warner(aTHX_ packWARN(WARN_SIGNAL), "No such signal: SIG%s",
+ pv_pretty(tmp, s, len, 0, NULL, NULL, 0));
+ }
return 0;
}
#ifdef HAS_SIGPROCMASK
@@ -1502,7 +1584,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
} else {
sv = NULL;
}
- if (sv && strEQ(s,"IGNORE")) {
+ if (sv && memEQs(s, len,"IGNORE")) {
if (i) {
#ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
PL_sig_ignoring[i] = 1;
@@ -1512,7 +1594,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
#endif
}
}
- else if (!sv || strEQ(s,"DEFAULT") || !len) {
+ else if (!sv || memEQs(s, len,"DEFAULT") || !len) {
if (i) {
#ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
PL_sig_defaulting[i] = 1;
@@ -1555,7 +1637,7 @@ Perl_magic_setisa(pTHX_ SV *sv, MAGIC *mg)
PERL_UNUSED_ARG(sv);
/* Skip _isaelem because _isa will handle it shortly */
- if (PL_delaymagic & DM_ARRAY && mg->mg_type == PERL_MAGIC_isaelem)
+ if (PL_delaymagic & DM_ARRAY_ISA && mg->mg_type == PERL_MAGIC_isaelem)
return 0;
return magic_clearisa(NULL, mg);
@@ -1571,26 +1653,34 @@ Perl_magic_clearisa(pTHX_ SV *sv, MAGIC *mg)
PERL_ARGS_ASSERT_MAGIC_CLEARISA;
/* Bail out if destruction is going on */
- if(PL_dirty) return 0;
+ if(PL_phase == PERL_PHASE_DESTRUCT) return 0;
if (sv)
av_clear(MUTABLE_AV(sv));
- /* XXX Once it's possible, we need to
- detect that our @ISA is aliased in
- other stashes, and act on the stashes
- of all of the aliases */
+ if (SvTYPE(mg->mg_obj) != SVt_PVGV && SvSMAGICAL(mg->mg_obj))
+ /* This occurs with setisa_elem magic, which calls this
+ same function. */
+ mg = mg_find(mg->mg_obj, PERL_MAGIC_isa);
+
+ if (SvTYPE(mg->mg_obj) == SVt_PVAV) { /* multiple stashes */
+ SV **svp = AvARRAY((AV *)mg->mg_obj);
+ I32 items = AvFILLp((AV *)mg->mg_obj) + 1;
+ while (items--) {
+ stash = GvSTASH((GV *)*svp++);
+ if (stash && HvENAME(stash)) mro_isa_changed_in(stash);
+ }
+
+ return 0;
+ }
- /* The first case occurs via setisa,
- the second via setisa_elem, which
- calls this same magic */
stash = GvSTASH(
- SvTYPE(mg->mg_obj) == SVt_PVGV
- ? (const GV *)mg->mg_obj
- : (const GV *)mg_find(mg->mg_obj, PERL_MAGIC_isa)->mg_obj
+ (const GV *)mg->mg_obj
);
- if (stash)
+ /* The stash may have been detached from the symbol table, so check its
+ name before doing anything. */
+ if (stash && HvENAME_get(stash))
mro_isa_changed_in(stash);
return 0;
@@ -1620,7 +1710,7 @@ Perl_magic_getnkeys(pTHX_ SV *sv, MAGIC *mg)
if (hv) {
(void) hv_iterinit(hv);
if (! SvTIED_mg((const SV *)hv, PERL_MAGIC_tied))
- i = HvKEYS(hv);
+ i = HvUSEDKEYS(hv);
else {
while (hv_iternext(hv))
i++;
@@ -1642,55 +1732,127 @@ Perl_magic_setnkeys(pTHX_ SV *sv, MAGIC *mg)
return 0;
}
-/* caller is responsible for stack switching/cleanup */
-STATIC int
-S_magic_methcall(pTHX_ SV *sv, const MAGIC *mg, const char *meth, I32 flags, int n, SV *val)
+/*
+=for apidoc magic_methcall
+
+Invoke a magic method (like FETCH).
+
+C and C are the tied thingy and the tie magic.
+
+C is the name of the method to call.
+
+C is the number of args (in addition to $self) to pass to the method.
+
+The C can be:
+
+ G_DISCARD invoke method with G_DISCARD flag and don't
+ return a value
+ G_UNDEF_FILL fill the stack with argc pointers to
+ PL_sv_undef
+
+The arguments themselves are any values following the C argument.
+
+Returns the SV (if any) returned by the method, or NULL on failure.
+
+
+=cut
+*/
+
+SV*
+Perl_magic_methcall(pTHX_ SV *sv, const MAGIC *mg, const char *meth, U32 flags,
+ U32 argc, ...)
{
dVAR;
dSP;
+ SV* ret = NULL;
PERL_ARGS_ASSERT_MAGIC_METHCALL;
+ ENTER;
+
+ if (flags & G_WRITING_TO_STDERR) {
+ SAVETMPS;
+
+ save_re_context();
+ SAVESPTR(PL_stderrgv);
+ PL_stderrgv = NULL;
+ }
+
+ PUSHSTACKi(PERLSI_MAGIC);
PUSHMARK(SP);
- EXTEND(SP, n);
+
+ EXTEND(SP, argc+1);
PUSHs(SvTIED_obj(sv, mg));
- if (n > 1) {
- if (mg->mg_ptr) {
- if (mg->mg_len >= 0)
- mPUSHp(mg->mg_ptr, mg->mg_len);
- else if (mg->mg_len == HEf_SVKEY)
- PUSHs(MUTABLE_SV(mg->mg_ptr));
+ if (flags & G_UNDEF_FILL) {
+ while (argc--) {
+ PUSHs(&PL_sv_undef);
}
- else if (mg->mg_type == PERL_MAGIC_tiedelem) {
- mPUSHi(mg->mg_len);
- }
- }
- if (n > 2) {
- PUSHs(val);
+ } else if (argc > 0) {
+ va_list args;
+ va_start(args, argc);
+
+ do {
+ SV *const sv = va_arg(args, SV *);
+ PUSHs(sv);
+ } while (--argc);
+
+ va_end(args);
}
PUTBACK;
+ if (flags & G_DISCARD) {
+ call_method(meth, G_SCALAR|G_DISCARD);
+ }
+ else {
+ if (call_method(meth, G_SCALAR))
+ ret = *PL_stack_sp--;
+ }
+ POPSTACK;
+ if (flags & G_WRITING_TO_STDERR)
+ FREETMPS;
+ LEAVE;
+ return ret;
+}
+
+
+/* wrapper for magic_methcall that creates the first arg */
+
+STATIC SV*
+S_magic_methcall1(pTHX_ SV *sv, const MAGIC *mg, const char *meth, U32 flags,
+ int n, SV *val)
+{
+ dVAR;
+ SV* arg1 = NULL;
- return call_method(meth, flags);
+ PERL_ARGS_ASSERT_MAGIC_METHCALL1;
+
+ if (mg->mg_ptr) {
+ if (mg->mg_len >= 0) {
+ arg1 = newSVpvn_flags(mg->mg_ptr, mg->mg_len, SVs_TEMP);
+ }
+ else if (mg->mg_len == HEf_SVKEY)
+ arg1 = MUTABLE_SV(mg->mg_ptr);
+ }
+ else if (mg->mg_type == PERL_MAGIC_tiedelem) {
+ arg1 = newSViv((IV)(mg->mg_len));
+ sv_2mortal(arg1);
+ }
+ if (!arg1) {
+ return Perl_magic_methcall(aTHX_ sv, mg, meth, flags, n - 1, val);
+ }
+ return Perl_magic_methcall(aTHX_ sv, mg, meth, flags, n, arg1, val);
}
STATIC int
S_magic_methpack(pTHX_ SV *sv, const MAGIC *mg, const char *meth)
{
- dVAR; dSP;
+ dVAR;
+ SV* ret;
PERL_ARGS_ASSERT_MAGIC_METHPACK;
- ENTER;
- SAVETMPS;
- PUSHSTACKi(PERLSI_MAGIC);
-
- if (magic_methcall(sv, mg, meth, G_SCALAR, 2, NULL)) {
- sv_setsv(sv, *PL_stack_sp--);
- }
-
- POPSTACK;
- FREETMPS;
- LEAVE;
+ ret = magic_methcall1(sv, mg, meth, 0, 1, NULL);
+ if (ret)
+ sv_setsv(sv, ret);
return 0;
}
@@ -1708,7 +1870,7 @@ Perl_magic_getpack(pTHX_ SV *sv, MAGIC *mg)
int
Perl_magic_setpack(pTHX_ SV *sv, MAGIC *mg)
{
- dVAR; dSP;
+ dVAR;
MAGIC *tmg;
SV *val;
@@ -1733,11 +1895,7 @@ Perl_magic_setpack(pTHX_ SV *sv, MAGIC *mg)
else
val = sv;
- ENTER;
- PUSHSTACKi(PERLSI_MAGIC);
- magic_methcall(sv, mg, "STORE", G_SCALAR|G_DISCARD, 3, val);
- POPSTACK;
- LEAVE;
+ magic_methcall1(sv, mg, "STORE", G_DISCARD, 2, val);
return 0;
}
@@ -1753,69 +1911,44 @@ Perl_magic_clearpack(pTHX_ SV *sv, MAGIC *mg)
U32
Perl_magic_sizepack(pTHX_ SV *sv, MAGIC *mg)
{
- dVAR; dSP;
+ dVAR;
I32 retval = 0;
+ SV* retsv;
PERL_ARGS_ASSERT_MAGIC_SIZEPACK;
- ENTER;
- SAVETMPS;
- PUSHSTACKi(PERLSI_MAGIC);
- if (magic_methcall(sv, mg, "FETCHSIZE", G_SCALAR, 2, NULL)) {
- sv = *PL_stack_sp--;
- retval = SvIV(sv)-1;
+ retsv = magic_methcall1(sv, mg, "FETCHSIZE", 0, 1, NULL);
+ if (retsv) {
+ retval = SvIV(retsv)-1;
if (retval < -1)
Perl_croak(aTHX_ "FETCHSIZE returned a negative value");
}
- POPSTACK;
- FREETMPS;
- LEAVE;
return (U32) retval;
}
int
Perl_magic_wipepack(pTHX_ SV *sv, MAGIC *mg)
{
- dVAR; dSP;
+ dVAR;
PERL_ARGS_ASSERT_MAGIC_WIPEPACK;
- ENTER;
- PUSHSTACKi(PERLSI_MAGIC);
- PUSHMARK(SP);
- XPUSHs(SvTIED_obj(sv, mg));
- PUTBACK;
- call_method("CLEAR", G_SCALAR|G_DISCARD);
- POPSTACK;
- LEAVE;
-
+ Perl_magic_methcall(aTHX_ sv, mg, "CLEAR", G_DISCARD, 0);
return 0;
}
int
Perl_magic_nextpack(pTHX_ SV *sv, MAGIC *mg, SV *key)
{
- dVAR; dSP;
- const char * const meth = SvOK(key) ? "NEXTKEY" : "FIRSTKEY";
+ dVAR;
+ SV* ret;
PERL_ARGS_ASSERT_MAGIC_NEXTPACK;
- ENTER;
- SAVETMPS;
- PUSHSTACKi(PERLSI_MAGIC);
- PUSHMARK(SP);
- EXTEND(SP, 2);
- PUSHs(SvTIED_obj(sv, mg));
- if (SvOK(key))
- PUSHs(key);
- PUTBACK;
-
- if (call_method(meth, G_SCALAR))
- sv_setsv(key, *PL_stack_sp--);
-
- POPSTACK;
- FREETMPS;
- LEAVE;
+ ret = SvOK(key) ? Perl_magic_methcall(aTHX_ sv, mg, "NEXTKEY", 0, 1, key)
+ : Perl_magic_methcall(aTHX_ sv, mg, "FIRSTKEY", 0, 0);
+ if (ret)
+ sv_setsv(key,ret);
return 0;
}
@@ -1830,7 +1963,7 @@ Perl_magic_existspack(pTHX_ SV *sv, const MAGIC *mg)
SV *
Perl_magic_scalarpack(pTHX_ HV *hv, MAGIC *mg)
{
- dVAR; dSP;
+ dVAR;
SV *retval;
SV * const tied = SvTIED_obj(MUTABLE_SV(hv), mg);
HV * const pkg = SvSTASH((const SV *)SvRV(tied));
@@ -1850,19 +1983,9 @@ Perl_magic_scalarpack(pTHX_ HV *hv, MAGIC *mg)
}
/* there is a SCALAR method that we can call */
- ENTER;
- PUSHSTACKi(PERLSI_MAGIC);
- PUSHMARK(SP);
- EXTEND(SP, 1);
- PUSHs(tied);
- PUTBACK;
-
- if (call_method("SCALAR", G_SCALAR))
- retval = *PL_stack_sp--;
- else
+ retval = Perl_magic_methcall(aTHX_ MUTABLE_SV(hv), mg, "SCALAR", 0, 0);
+ if (!retval)
retval = &PL_sv_undef;
- POPSTACK;
- LEAVE;
return retval;
}
@@ -1899,7 +2022,7 @@ Perl_magic_getarylen(pTHX_ SV *sv, const MAGIC *mg)
PERL_ARGS_ASSERT_MAGIC_GETARYLEN;
if (obj) {
- sv_setiv(sv, AvFILL(obj) + CopARYBASE_get(PL_curcop));
+ sv_setiv(sv, AvFILL(obj));
} else {
SvOK_off(sv);
}
@@ -1915,7 +2038,7 @@ Perl_magic_setarylen(pTHX_ SV *sv, MAGIC *mg)
PERL_ARGS_ASSERT_MAGIC_SETARYLEN;
if (obj) {
- av_fill(obj, SvIV(sv) - CopARYBASE_get(PL_curcop));
+ av_fill(obj, SvIV(sv));
} else {
Perl_ck_warner(aTHX_ packWARN(WARN_MISC),
"Attempt to set length of freed array");
@@ -1963,7 +2086,7 @@ Perl_magic_getpos(pTHX_ SV *sv, MAGIC *mg)
I32 i = found->mg_len;
if (DO_UTF8(lsv))
sv_pos_b2u(lsv, &i);
- sv_setiv(sv, i + CopARYBASE_get(PL_curcop));
+ sv_setiv(sv, i);
return 0;
}
}
@@ -2004,7 +2127,7 @@ Perl_magic_setpos(pTHX_ SV *sv, MAGIC *mg)
}
len = SvPOK(lsv) ? SvCUR(lsv) : sv_len(lsv);
- pos = SvIV(sv) - CopARYBASE_get(PL_curcop);
+ pos = SvIV(sv);
if (DO_UTF8(lsv)) {
ulen = sv_len_utf8(lsv);
@@ -2069,10 +2192,15 @@ Perl_magic_setsubstr(pTHX_ SV *sv, MAGIC *mg)
PERL_ARGS_ASSERT_MAGIC_SETSUBSTR;
PERL_UNUSED_ARG(mg);
+ SvGETMAGIC(lsv);
+ if (SvROK(lsv))
+ Perl_ck_warner(aTHX_ packWARN(WARN_SUBSTR),
+ "Attempt to use reference as lvalue in substr"
+ );
if (DO_UTF8(sv)) {
sv_utf8_upgrade(lsv);
lvoff = sv_pos_u2b_flags(lsv, lvoff, &lvlen, SV_CONST_RETURN);
- sv_insert(lsv, lvoff, lvlen, tmps, len);
+ sv_insert_flags(lsv, lvoff, lvlen, tmps, len, 0);
LvTARGLEN(sv) = sv_len_utf8(sv);
SvUTF8_on(lsv);
}
@@ -2081,11 +2209,11 @@ Perl_magic_setsubstr(pTHX_ SV *sv, MAGIC *mg)
lvoff = sv_pos_u2b_flags(lsv, lvoff, &lvlen, SV_CONST_RETURN);
LvTARGLEN(sv) = len;
utf8 = (char*)bytes_to_utf8((U8*)tmps, &len);
- sv_insert(lsv, lvoff, lvlen, utf8, len);
+ sv_insert_flags(lsv, lvoff, lvlen, utf8, len, 0);
Safefree(utf8);
}
else {
- sv_insert(lsv, lvoff, lvlen, tmps, len);
+ sv_insert_flags(lsv, lvoff, lvlen, tmps, len, 0);
LvTARGLEN(sv) = len;
}
@@ -2237,7 +2365,8 @@ int
Perl_magic_killbackrefs(pTHX_ SV *sv, MAGIC *mg)
{
PERL_ARGS_ASSERT_MAGIC_KILLBACKREFS;
- return Perl_sv_kill_backrefs(aTHX_ sv, MUTABLE_AV(mg->mg_obj));
+ Perl_sv_kill_backrefs(aTHX_ sv, MUTABLE_AV(mg->mg_obj));
+ return 0;
}
int
@@ -2245,9 +2374,8 @@ Perl_magic_setmglob(pTHX_ SV *sv, MAGIC *mg)
{
PERL_ARGS_ASSERT_MAGIC_SETMGLOB;
PERL_UNUSED_CONTEXT;
+ PERL_UNUSED_ARG(sv);
mg->mg_len = -1;
- if (!isGV_with_GP(sv))
- SvSCREAM_off(sv);
return 0;
}
@@ -2274,9 +2402,11 @@ Perl_magic_setregexp(pTHX_ SV *sv, MAGIC *mg)
} else if (type == PERL_MAGIC_bm) {
SvTAIL_off(sv);
SvVALID_off(sv);
+ } else if (type == PERL_MAGIC_study) {
+ if (!isGV_with_GP(sv))
+ SvSCREAM_off(sv);
} else {
assert(type == PERL_MAGIC_fm);
- SvCOMPILED_off(sv);
}
return sv_unmagic(sv, type);
}
@@ -2325,6 +2455,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
const char * const remaining = mg->mg_ptr + 1;
I32 i;
STRLEN len;
+ MAGIC *tmg;
PERL_ARGS_ASSERT_MAGIC_SET;
@@ -2350,17 +2481,32 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
setparen:
if (PL_curpm && (rx = PM_GETRE(PL_curpm))) {
CALLREG_NUMBUF_STORE((REGEXP * const)rx,paren,sv);
- break;
} else {
/* Croak with a READONLY error when a numbered match var is
* set without a previous pattern match. Unless it's C
*/
if (!PL_localizing) {
- Perl_croak(aTHX_ "%s", PL_no_modify);
+ Perl_croak_no_modify(aTHX);
}
}
+ break;
case '\001': /* ^A */
sv_setsv(PL_bodytarget, sv);
+ FmLINES(PL_bodytarget) = 0;
+ if (SvPOK(PL_bodytarget)) {
+ char *s = SvPVX(PL_bodytarget);
+ while ( ((s = strchr(s, '\n'))) ) {
+ FmLINES(PL_bodytarget)++;
+ s++;
+ }
+ }
+ /* mg_set() has temporarily made sv non-magical */
+ if (PL_tainting) {
+ if ((tmg = mg_find(sv,PERL_MAGIC_taint)) && tmg->mg_len & 1)
+ SvTAINTED_on(PL_bodytarget);
+ else
+ SvTAINTED_off(PL_bodytarget);
+ }
break;
case '\003': /* ^C */
PL_minus_c = cBOOL(SvIV(sv));
@@ -2457,6 +2603,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
} else if (strEQ(remaining, "OSTMATCH")) { /* $^POSTMATCH */
goto do_postmatch;
}
+ break;
case '\024': /* ^T */
#ifdef BIG_TIME
PL_basetime = (Time_t)(SvNOK(sv) ? SvNVX(sv) : sv_2nv(sv));
@@ -2531,33 +2678,25 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
IoLINES(GvIOp(PL_last_in_gv)) = SvIV(sv);
break;
case '^':
- if (isGV_with_GP(PL_defoutgv)) {
- Safefree(IoTOP_NAME(GvIOp(PL_defoutgv)));
- s = IoTOP_NAME(GvIOp(PL_defoutgv)) = savesvpv(sv);
- IoTOP_GV(GvIOp(PL_defoutgv)) = gv_fetchsv(sv, GV_ADD, SVt_PVIO);
- }
+ Safefree(IoTOP_NAME(GvIOp(PL_defoutgv)));
+ s = IoTOP_NAME(GvIOp(PL_defoutgv)) = savesvpv(sv);
+ IoTOP_GV(GvIOp(PL_defoutgv)) = gv_fetchsv(sv, GV_ADD, SVt_PVIO);
break;
case '~':
- if (isGV_with_GP(PL_defoutgv)) {
- Safefree(IoFMT_NAME(GvIOp(PL_defoutgv)));
- s = IoFMT_NAME(GvIOp(PL_defoutgv)) = savesvpv(sv);
- IoFMT_GV(GvIOp(PL_defoutgv)) = gv_fetchsv(sv, GV_ADD, SVt_PVIO);
- }
+ Safefree(IoFMT_NAME(GvIOp(PL_defoutgv)));
+ s = IoFMT_NAME(GvIOp(PL_defoutgv)) = savesvpv(sv);
+ IoFMT_GV(GvIOp(PL_defoutgv)) = gv_fetchsv(sv, GV_ADD, SVt_PVIO);
break;
case '=':
- if (isGV_with_GP(PL_defoutgv))
- IoPAGE_LEN(GvIOp(PL_defoutgv)) = (SvIV(sv));
+ IoPAGE_LEN(GvIOp(PL_defoutgv)) = (SvIV(sv));
break;
case '-':
- if (isGV_with_GP(PL_defoutgv)) {
- IoLINES_LEFT(GvIOp(PL_defoutgv)) = (SvIV(sv));
- if (IoLINES_LEFT(GvIOp(PL_defoutgv)) < 0L)
+ IoLINES_LEFT(GvIOp(PL_defoutgv)) = (SvIV(sv));
+ if (IoLINES_LEFT(GvIOp(PL_defoutgv)) < 0L)
IoLINES_LEFT(GvIOp(PL_defoutgv)) = 0L;
- }
break;
case '%':
- if (isGV_with_GP(PL_defoutgv))
- IoPAGE(GvIOp(PL_defoutgv)) = (SvIV(sv));
+ IoPAGE(GvIOp(PL_defoutgv)) = (SvIV(sv));
break;
case '|':
{
@@ -2589,9 +2728,6 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
PL_ors_sv = NULL;
}
break;
- case '[':
- CopARYBASE_set(&PL_compiling, SvIV(sv));
- break;
case '?':
#ifdef COMPLEX_STATUS
if (PL_localizing == 2) {
@@ -2689,7 +2825,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
(void)setregid((Gid_t)PL_gid, (Gid_t)-1);
#else
#ifdef HAS_SETRESGID
- (void)setresgid((Gid_t)PL_gid, (Gid_t)-1, (Gid_t) 1);
+ (void)setresgid((Gid_t)PL_gid, (Gid_t)-1, (Gid_t) -1);
#else
if (PL_gid == PL_egid) /* special case $( = $) */
(void)PerlProc_setgid(PL_gid);
@@ -2766,6 +2902,17 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
case ':':
PL_chopset = SvPV_force(sv,len);
break;
+ case '$': /* $$ */
+ /* Store the pid in mg->mg_obj so we can tell when a fork has
+ occurred. mg->mg_obj points to *$ by default, so clear it. */
+ if (isGV(mg->mg_obj)) {
+ if (mg->mg_flags & MGf_REFCOUNTED) /* probably never true */
+ SvREFCNT_dec(mg->mg_obj);
+ mg->mg_flags |= MGf_REFCOUNTED;
+ mg->mg_obj = newSViv((IV)PerlProc_getpid());
+ }
+ else sv_setiv(mg->mg_obj, (IV)PerlProc_getpid());
+ break;
case '0':
LOCK_DOLLARZERO_MUTEX;
#ifdef HAS_SETPROCTITLE
@@ -2843,22 +2990,41 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
}
I32
-Perl_whichsig(pTHX_ const char *sig)
+Perl_whichsig_sv(pTHX_ SV *sigsv)
+{
+ const char *sigpv;
+ STRLEN siglen;
+ PERL_ARGS_ASSERT_WHICHSIG_SV;
+ PERL_UNUSED_CONTEXT;
+ sigpv = SvPV_const(sigsv, siglen);
+ return whichsig_pvn(sigpv, siglen);
+}
+
+I32
+Perl_whichsig_pv(pTHX_ const char *sig)
+{
+ PERL_ARGS_ASSERT_WHICHSIG_PV;
+ PERL_UNUSED_CONTEXT;
+ return whichsig_pvn(sig, strlen(sig));
+}
+
+I32
+Perl_whichsig_pvn(pTHX_ const char *sig, STRLEN len)
{
register char* const* sigv;
- PERL_ARGS_ASSERT_WHICHSIG;
+ PERL_ARGS_ASSERT_WHICHSIG_PVN;
PERL_UNUSED_CONTEXT;
for (sigv = (char* const*)PL_sig_name; *sigv; sigv++)
- if (strEQ(sig,*sigv))
+ if (strlen(*sigv) == len && memEQ(sig,*sigv, len))
return PL_sig_num[sigv - (char* const*)PL_sig_name];
#ifdef SIGCLD
- if (strEQ(sig,"CHLD"))
+ if (memEQs(sig, len, "CHLD"))
return SIGCLD;
#endif
#ifdef SIGCHLD
- if (strEQ(sig,"CLD"))
+ if (memEQs(sig, len, "CLD"))
return SIGCHLD;
#endif
return -1;
@@ -2866,7 +3032,7 @@ Perl_whichsig(pTHX_ const char *sig)
Signal_t
#if defined(HAS_SIGACTION) && defined(SA_SIGINFO)
-Perl_sighandler(int sig, siginfo_t *sip, void *uap PERL_UNUSED_DECL)
+Perl_sighandler(int sig, siginfo_t *sip, void *uap)
#else
Perl_sighandler(int sig)
#endif
@@ -2884,13 +3050,8 @@ Perl_sighandler(int sig)
OP *myop = PL_op;
U32 flags = 0;
XPV * const tXpv = PL_Xpv;
+ I32 old_ss_ix = PL_savestack_ix;
- if (PL_savestack_ix + 15 <= PL_savestack_max)
- flags |= 1;
- if (PL_markstack_ptr < PL_markstack_max - 2)
- flags |= 4;
- if (PL_scopestack_ix < PL_scopestack_max - 3)
- flags |= 16;
if (!PL_psig_ptr[sig]) {
PerlIO_printf(Perl_error_log, "Signal SIG%s received, but no signal handler set.\n",
@@ -2898,16 +3059,15 @@ Perl_sighandler(int sig)
exit(sig);
}
- /* Max number of items pushed there is 3*n or 4. We cannot fix
- infinity, so we fix 4 (in fact 5): */
- if (flags & 1) {
- PL_savestack_ix += 5; /* Protect save in progress. */
- SAVEDESTRUCTOR_X(S_unwind_handler_stack, (void*)&flags);
+ if (PL_signals & PERL_SIGNALS_UNSAFE_FLAG) {
+ /* Max number of items pushed there is 3*n or 4. We cannot fix
+ infinity, so we fix 4 (in fact 5): */
+ if (PL_savestack_ix + 15 <= PL_savestack_max) {
+ flags |= 1;
+ PL_savestack_ix += 5; /* Protect save in progress. */
+ SAVEDESTRUCTOR_X(S_unwind_handler_stack, NULL);
+ }
}
- if (flags & 4)
- PL_markstack_ptr++; /* Protect mark. */
- if (flags & 16)
- PL_scopestack_ix += 1;
/* sv_2cv is too complicated, try a simpler variant first: */
if (!SvROK(PL_psig_ptr[sig]) || !(cv = MUTABLE_CV(SvRV(PL_psig_ptr[sig])))
|| SvTYPE(cv) != SVt_PVCV) {
@@ -2924,15 +3084,16 @@ Perl_sighandler(int sig)
goto cleanup;
}
- if(PL_psig_name[sig]) {
- sv = SvREFCNT_inc_NN(PL_psig_name[sig]);
- flags |= 64;
-#if !defined(PERL_IMPLICIT_CONTEXT)
- PL_sig_sv = sv;
-#endif
- } else {
- sv = sv_newmortal();
- sv_setpv(sv,PL_sig_name[sig]);
+ sv = PL_psig_name[sig]
+ ? SvREFCNT_inc_NN(PL_psig_name[sig])
+ : newSVpv(PL_sig_name[sig],0);
+ flags |= 8;
+ SAVEFREESV(sv);
+
+ if (PL_signals & PERL_SIGNALS_UNSAFE_FLAG) {
+ /* make sure our assumption about the size of the SAVEs are correct:
+ * 3 for SAVEDESTRUCTOR_X, 2 for SAVEFREESV */
+ assert(old_ss_ix + 2 + ((flags & 1) ? 3+5 : 0) == PL_savestack_ix);
}
PUSHSTACKi(PERLSI_SIGNAL);
@@ -2973,31 +3134,32 @@ Perl_sighandler(int sig)
POPSTACK;
if (SvTRUE(ERRSV)) {
#ifndef PERL_MICRO
-#ifdef HAS_SIGPROCMASK
/* Handler "died", for example to get out of a restart-able read().
* Before we re-do that on its behalf re-enable the signal which was
* blocked by the system when we entered.
*/
- sigset_t set;
- sigemptyset(&set);
- sigaddset(&set,sig);
- sigprocmask(SIG_UNBLOCK, &set, NULL);
+#ifdef HAS_SIGPROCMASK
+#if defined(HAS_SIGACTION) && defined(SA_SIGINFO)
+ if (sip || uap)
+#endif
+ {
+ sigset_t set;
+ sigemptyset(&set);
+ sigaddset(&set,sig);
+ sigprocmask(SIG_UNBLOCK, &set, NULL);
+ }
#else
/* Not clear if this will work */
(void)rsignal(sig, SIG_IGN);
(void)rsignal(sig, PL_csighandlerp);
#endif
#endif /* !PERL_MICRO */
- Perl_die(aTHX_ NULL);
+ die_sv(ERRSV);
}
cleanup:
- if (flags & 1)
- PL_savestack_ix -= 8; /* Unprotect save in progress. */
- if (flags & 4)
- PL_markstack_ptr--;
- if (flags & 16)
- PL_scopestack_ix -= 1;
- if (flags & 64)
+ /* pop any of SAVEFREESV, SAVEDESTRUCTOR_X and "save in progress" */
+ PL_savestack_ix = old_ss_ix;
+ if (flags & 8)
SvREFCNT_dec(sv);
PL_op = myop; /* Apparently not needed... */
@@ -3013,6 +3175,7 @@ S_restore_magic(pTHX_ const void *p)
dVAR;
MGS* const mgs = SSPTR(PTR2IV(p), MGS*);
SV* const sv = mgs->mgs_sv;
+ bool bumped;
if (!sv)
return;
@@ -3044,6 +3207,7 @@ S_restore_magic(pTHX_ const void *p)
}
}
+ bumped = mgs->mgs_bumped;
mgs->mgs_sv = NULL; /* mark the MGS structure as restored */
/* If we're still on top of the stack, pop us off. (That condition
@@ -3055,31 +3219,44 @@ S_restore_magic(pTHX_ const void *p)
*/
if (PL_savestack_ix == mgs->mgs_ss_ix)
{
- I32 popval = SSPOPINT;
+ UV popval = SSPOPUV;
assert(popval == SAVEt_DESTRUCTOR_X);
PL_savestack_ix -= 2;
- popval = SSPOPINT;
- assert(popval == SAVEt_ALLOC);
- popval = SSPOPINT;
- PL_savestack_ix -= popval;
+ popval = SSPOPUV;
+ assert((popval & SAVE_MASK) == SAVEt_ALLOC);
+ PL_savestack_ix -= popval >> SAVE_TIGHT_SHIFT;
+ }
+ if (bumped) {
+ if (SvREFCNT(sv) == 1) {
+ /* We hold the last reference to this SV, which implies that the
+ SV was deleted as a side effect of the routines we called.
+ So artificially keep it alive a bit longer.
+ We avoid turning on the TEMP flag, which can cause the SV's
+ buffer to get stolen (and maybe other stuff). */
+ int was_temp = SvTEMP(sv);
+ sv_2mortal(sv);
+ if (!was_temp) {
+ SvTEMP_off(sv);
+ }
+ SvOK_off(sv);
+ }
+ else
+ SvREFCNT_dec(sv); /* undo the inc in S_save_magic() */
}
-
}
+/* clean up the mess created by Perl_sighandler().
+ * Note that this is only called during an exit in a signal handler;
+ * a die is trapped by the call_sv() and the SAVEDESTRUCTOR_X manually
+ * skipped over. */
+
static void
S_unwind_handler_stack(pTHX_ const void *p)
{
dVAR;
- const U32 flags = *(const U32*)p;
+ PERL_UNUSED_ARG(p);
- PERL_ARGS_ASSERT_UNWIND_HANDLER_STACK;
-
- if (flags & 1)
- PL_savestack_ix -= 5; /* Unprotect save in progress. */
-#if !defined(PERL_IMPLICIT_CONTEXT)
- if (flags & 64)
- SvREFCNT_dec(PL_sig_sv);
-#endif
+ PL_savestack_ix -= 5; /* Unprotect save in progress. */
}
/*
@@ -3110,8 +3287,8 @@ Perl_magic_sethint(pTHX_ SV *sv, MAGIC *mg)
Doing this here saves a lot of doing it manually in perl code (and
forgetting to do it, and consequent subtle errors. */
PL_hints |= HINT_LOCALIZE_HH;
- PL_compiling.cop_hints_hash
- = Perl_refcounted_he_new(aTHX_ PL_compiling.cop_hints_hash, key, sv);
+ CopHINTHASH_set(&PL_compiling,
+ cophh_store_sv(CopHINTHASH_get(&PL_compiling), key, 0, sv, 0));
return 0;
}
@@ -3136,9 +3313,9 @@ Perl_magic_clearhint(pTHX_ SV *sv, MAGIC *mg)
PERL_UNUSED_ARG(sv);
PL_hints |= HINT_LOCALIZE_HH;
- PL_compiling.cop_hints_hash
- = Perl_refcounted_he_new(aTHX_ PL_compiling.cop_hints_hash,
- MUTABLE_SV(mg->mg_ptr), &PL_sv_placeholder);
+ CopHINTHASH_set(&PL_compiling,
+ cophh_delete_sv(CopHINTHASH_get(&PL_compiling),
+ MUTABLE_SV(mg->mg_ptr), 0, 0));
return 0;
}
@@ -3155,10 +3332,8 @@ Perl_magic_clearhints(pTHX_ SV *sv, MAGIC *mg)
PERL_ARGS_ASSERT_MAGIC_CLEARHINTS;
PERL_UNUSED_ARG(sv);
PERL_UNUSED_ARG(mg);
- if (PL_compiling.cop_hints_hash) {
- Perl_refcounted_he_free(aTHX_ PL_compiling.cop_hints_hash);
- PL_compiling.cop_hints_hash = NULL;
- }
+ cophh_free(CopHINTHASH_get(&PL_compiling));
+ CopHINTHASH_set(&PL_compiling, cophh_new_empty());
return 0;
}