summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embed.fnc10
-rw-r--r--embed.h4
-rw-r--r--pp_ctl.c8
-rw-r--r--proto.h14
-rw-r--r--t/op/die.t20
-rw-r--r--t/op/eval.t17
-rw-r--r--util.c4
7 files changed, 62 insertions, 15 deletions
diff --git a/embed.fnc b/embed.fnc
index 8af314950c..4cac03ca8c 100644
--- a/embed.fnc
+++ b/embed.fnc
@@ -2558,7 +2558,7 @@ Adp |char * |pv_uni_display |NN SV *dsv \
|UV flags
: FIXME - either make it public, or stop exporting it. (Data::Alias uses this)
: Used in gv.c, op.c, toke.c
-EXp |void |qerror |NN SV *err
+EXp |void |qerror |NULLOK SV *err
Adp |char * |rcpv_copy |NULLOK char * const pv
Adp |char * |rcpv_free |NULLOK char * const pv
Aadp |char * |rcpv_new |NULLOK const char * const pv \
@@ -4831,6 +4831,11 @@ S |void |save_lines |NULLOK AV *array \
RS |PerlIO *|doopen_pm |NN SV *name
# endif /* !defined(PERL_DISABLE_PMC) */
#endif /* defined(PERL_IN_PP_CTL_C) */
+#if defined(PERL_IN_PP_CTL_C) || defined(PERL_IN_UTIL_C)
+p |bool |invoke_exception_hook \
+ |NULLOK SV *ex \
+ |bool warn
+#endif /* defined(PERL_IN_PP_CTL_C) || defined(PERL_IN_UTIL_C) */
#if defined(PERL_IN_PP_HOT_C)
S |void |do_oddball |NN SV **oddkey \
|NN SV **firstkey
@@ -5853,9 +5858,6 @@ S |void |warn_on_first_deprecated_use \
#endif /* defined(PERL_IN_UTF8_C) */
#if defined(PERL_IN_UTIL_C)
S |bool |ckwarn_common |U32 w
-S |bool |invoke_exception_hook \
- |NULLOK SV *ex \
- |bool warn
S |SV * |mess_alloc
S |SV * |with_queued_errors \
|NN SV *ex
diff --git a/embed.h b/embed.h
index b0d23f0a47..75f20734b9 100644
--- a/embed.h
+++ b/embed.h
@@ -1491,6 +1491,9 @@
# define doopen_pm(a) S_doopen_pm(aTHX_ a)
# endif /* !defined(PERL_DISABLE_PMC) */
# endif /* defined(PERL_IN_PP_CTL_C) */
+# if defined(PERL_IN_PP_CTL_C) || defined(PERL_IN_UTIL_C)
+# define invoke_exception_hook(a,b) Perl_invoke_exception_hook(aTHX_ a,b)
+# endif /* defined(PERL_IN_PP_CTL_C) || defined(PERL_IN_UTIL_C) */
# if defined(PERL_IN_PP_HOT_C)
# define do_oddball(a,b) S_do_oddball(aTHX_ a,b)
# define opmethod_stash(a) S_opmethod_stash(aTHX_ a)
@@ -1622,7 +1625,6 @@
# endif /* defined(PERL_IN_UTF8_C) */
# if defined(PERL_IN_UTIL_C)
# define ckwarn_common(a) S_ckwarn_common(aTHX_ a)
-# define invoke_exception_hook(a,b) S_invoke_exception_hook(aTHX_ a,b)
# define mess_alloc() S_mess_alloc(aTHX)
# define with_queued_errors(a) S_with_queued_errors(aTHX_ a)
# if defined(PERL_MEM_LOG) && !defined(PERL_MEM_LOG_NOIMPL)
diff --git a/pp_ctl.c b/pp_ctl.c
index de5c27cff5..6ee2360f62 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -3804,6 +3804,9 @@ S_doeval_compile(pTHX_ U8 gimme, CV* outside, U32 seq, HV *hh)
* various vars restored. This block applies similar steps after
* the other "failed to compile" cases in yyparse, eg, where
* yystatus=1, "failed, but did not die". */
+
+ if (!in_require)
+ invoke_exception_hook(ERRSV,FALSE);
if (PL_eval_root) {
op_free(PL_eval_root);
PL_eval_root = NULL;
@@ -3811,6 +3814,10 @@ S_doeval_compile(pTHX_ U8 gimme, CV* outside, U32 seq, HV *hh)
SP = PL_stack_base + POPMARK; /* pop original mark */
cx = CX_CUR();
assert(CxTYPE(cx) == CXt_EVAL);
+ /* If we are in an eval we need to make sure that $SIG{__DIE__}
+ * handler is invoked so we simulate that part of the
+ * Perl_die_unwind() process. In a require we will croak
+ * so it will happen there. */
/* pop the CXt_EVAL, and if was a require, croak */
S_pop_eval_context_maybe_croak(aTHX_ cx, ERRSV, 2);
}
@@ -3824,6 +3831,7 @@ S_doeval_compile(pTHX_ U8 gimme, CV* outside, U32 seq, HV *hh)
if (!*(SvPV_nolen_const(errsv)))
sv_setpvs(errsv, "Compilation error");
+
if (gimme != G_LIST) PUSHs(&PL_sv_undef);
PUTBACK;
return FALSE;
diff --git a/proto.h b/proto.h
index 518422ed32..fa4b495f83 100644
--- a/proto.h
+++ b/proto.h
@@ -3578,8 +3578,7 @@ Perl_pv_uni_display(pTHX_ SV *dsv, const U8 *spv, STRLEN len, STRLEN pvlim, UV f
PERL_CALLCONV void
Perl_qerror(pTHX_ SV *err);
-#define PERL_ARGS_ASSERT_QERROR \
- assert(err)
+#define PERL_ARGS_ASSERT_QERROR
PERL_CALLCONV char *
Perl_rcpv_copy(pTHX_ char * const pv);
@@ -7945,6 +7944,13 @@ S_path_is_searchable(const char *name)
# endif /* !defined(PERL_NO_INLINE_FUNCTIONS) */
#endif /* defined(PERL_IN_PP_CTL_C) */
+#if defined(PERL_IN_PP_CTL_C) || defined(PERL_IN_UTIL_C)
+PERL_CALLCONV bool
+Perl_invoke_exception_hook(pTHX_ SV *ex, bool warn)
+ __attribute__visibility__("hidden");
+# define PERL_ARGS_ASSERT_INVOKE_EXCEPTION_HOOK
+
+#endif /* defined(PERL_IN_PP_CTL_C) || defined(PERL_IN_UTIL_C) */
#if defined(PERL_IN_PP_HOT_C)
STATIC void
S_do_oddball(pTHX_ SV **oddkey, SV **firstkey);
@@ -9537,10 +9543,6 @@ STATIC bool
S_ckwarn_common(pTHX_ U32 w);
# define PERL_ARGS_ASSERT_CKWARN_COMMON
-STATIC bool
-S_invoke_exception_hook(pTHX_ SV *ex, bool warn);
-# define PERL_ARGS_ASSERT_INVOKE_EXCEPTION_HOOK
-
STATIC SV *
S_mess_alloc(pTHX);
# define PERL_ARGS_ASSERT_MESS_ALLOC
diff --git a/t/op/die.t b/t/op/die.t
index eec1e8e485..c6579373f7 100644
--- a/t/op/die.t
+++ b/t/op/die.t
@@ -6,7 +6,7 @@ BEGIN {
set_up_inc('../lib');
}
-plan tests => 21;
+plan tests => 26;
use utf8; # Tell EBCDIC translator to make this UTF-8,
@@ -101,10 +101,26 @@ like($@, qr/\.{3}propagated at/, '... and appends a phrase');
like($@."", qr/100\t\.{3}propagated at/,
'check non-PVs in $@ are propagated');
}
+{
+ my @error;
+ local $SIG{__DIE__}= sub { push @error, @_ };
+ use strict;
+ my $ok= eval '$intentionally_missing+1';
+ my $eval_error= $@;
+ is($ok,undef,"eval should return undef");
+ is(0+@error,1,"we should have captured 1 error via __DIE__");
+ like( $error[0],
+ qr/Global symbol \"\$intentionally_missing\"/,
+ "The __DIE__ handler should have seen this message");
+ like( $eval_error,
+ qr/Global symbol \"\$intentionally_missing\"/,
+ "The eval error in '\$@' should contain this message");
+ is( $error[0], $eval_error,
+ "__DIE__ handler and \$@ should be the same");
+}
TODO: {
local $TODO = 'RT #4821: die qr{x} does not check termination';
my $out = runperl(prog => 'die qr{x}', stderr => 1);
like($out, qr/at -e line 1./, 'RT #4821: output from die qr{x}');
}
-
diff --git a/t/op/eval.t b/t/op/eval.t
index 3561e2f0b7..f2f06b1a74 100644
--- a/t/op/eval.t
+++ b/t/op/eval.t
@@ -738,3 +738,20 @@ pass("eval in freed package does not crash");
"No segfault inside sort: $sort_line");
}
}
+{
+ # test that all of these cases behave the same
+ for my $fragment ('bar', '1+;', '1+;' x 11, 's/', ']') {
+ fresh_perl_is(
+ # code:
+ 'use strict; use warnings; $SIG{__DIE__} = sub { die "X" }; ' .
+ 'eval { eval "'.$fragment.'"; print "after eval $@"; };' .
+ 'if ($@) { print "outer eval $@" }',
+ # wanted:
+ "after eval X at - line 1.",
+ # opts:
+ {},
+ # name:
+ "test that nested eval '$fragment' calls sig die as expected"
+ );
+ }
+}
diff --git a/util.c b/util.c
index 8590b3a4bc..21abe57d46 100644
--- a/util.c
+++ b/util.c
@@ -1717,8 +1717,8 @@ S_with_queued_errors(pTHX_ SV *ex)
return ex;
}
-STATIC bool
-S_invoke_exception_hook(pTHX_ SV *ex, bool warn)
+bool
+Perl_invoke_exception_hook(pTHX_ SV *ex, bool warn)
{
HV *stash;
GV *gv;