summaryrefslogtreecommitdiff
path: root/pp_ctl.c
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2016-06-30 10:12:06 +0100
committerDavid Mitchell <davem@iabyn.com>2016-07-01 09:35:14 +0100
commit8c86f0238ecb5f32c2e7fba36e3edfdb54069068 (patch)
tree3174d5aeb604bc4585057ec303dc370b5cb8cb11 /pp_ctl.c
parent2a1e0dfedad09204e5328c32f1fcf915153a191c (diff)
downloadperl-8c86f0238ecb5f32c2e7fba36e3edfdb54069068.tar.gz
die_unwind(): mortalise, not mortalcopy the err SV
The error string needs to be preserved while unwinding the stacks, but doing a simple sv_2mortal() and bumping the reference count seems sufficient, rather than making a complete copy. Also, avoid the mortalised SV's buffer from being stolen by using the SV_NOSTEAL flag rather than unsetting SvTEMP. Finally, add some basic comments above Perl_die_unwind() explaining what it's for.
Diffstat (limited to 'pp_ctl.c')
-rw-r--r--pp_ctl.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/pp_ctl.c b/pp_ctl.c
index 86c83e77bb..5a66e267a7 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -1636,17 +1636,26 @@ S_pop_eval_context_maybe_croak(pTHX_ PERL_CONTEXT *cx, SV *errsv, int action)
}
+/* die_unwind(): this is the final destination for the various croak()
+ * functions. If we're in an eval, unwind the context and other stacks
+ * back to the top-most CXt_EVAL and set $@ to msv; otherwise print msv
+ * to STDERR and initiate an exit. Note that if the CXt_EVAL popped back
+ * to is a require the exception will be rethrown, as requires don't
+ * actually trap exceptions.
+ */
void
Perl_die_unwind(pTHX_ SV *msv)
{
- SV *exceptsv = sv_mortalcopy(msv);
+ SV *exceptsv = msv;
U8 in_eval = PL_in_eval;
PERL_ARGS_ASSERT_DIE_UNWIND;
if (in_eval) {
I32 cxix;
+ exceptsv = sv_2mortal(SvREFCNT_inc_simple_NN(exceptsv));
+
/*
* Historically, perl used to set ERRSV ($@) early in the die
* process and rely on it not getting clobbered during unwinding.
@@ -1676,10 +1685,9 @@ Perl_die_unwind(pTHX_ SV *msv)
* perls 5.13.{1..7} which had late setting of $@ without this
* early-setting hack.
*/
- if (!(in_eval & EVAL_KEEPERR)) {
- SvTEMP_off(exceptsv);
- sv_setsv(ERRSV, exceptsv);
- }
+ if (!(in_eval & EVAL_KEEPERR))
+ sv_setsv_flags(ERRSV, exceptsv,
+ (SV_GMAGIC|SV_DO_COW_SVSETSV|SV_NOSTEAL));
if (in_eval & EVAL_KEEPERR) {
Perl_ck_warner(aTHX_ packWARN(WARN_MISC), "\t(in cleanup) %"SVf,