diff options
author | Erlang/OTP <[email protected]> | 2019-05-29 13:24:42 +0200 |
---|---|---|
committer | Erlang/OTP <[email protected]> | 2019-05-29 13:24:42 +0200 |
commit | 9afe8ad5eb15c1a205ca428d84c06d4a1fe888cc (patch) | |
tree | b04064045b42f49c71c292ced68b0e4f6485aa60 /erts/emulator/beam | |
parent | 1f61a273a53ac8fe48be1de0c86b33c82a84ebbd (diff) | |
parent | 5959fb00182048d50f55d04684723d383d1aeee8 (diff) | |
download | otp-9afe8ad5eb15c1a205ca428d84c06d4a1fe888cc.tar.gz otp-9afe8ad5eb15c1a205ca428d84c06d4a1fe888cc.tar.bz2 otp-9afe8ad5eb15c1a205ca428d84c06d4a1fe888cc.zip |
Merge branch 'bjorn/erts/fix-wrong-class/ERIERL-367/OTP-15834' into maint-22
* bjorn/erts/fix-wrong-class/ERIERL-367/OTP-15834:
Fix sticky class in exception
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r-- | erts/emulator/beam/beam_emu.c | 20 | ||||
-rw-r--r-- | erts/emulator/beam/instrs.tab | 17 |
2 files changed, 34 insertions, 3 deletions
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c index bae64afb97..07c16e3415 100644 --- a/erts/emulator/beam/beam_emu.c +++ b/erts/emulator/beam/beam_emu.c @@ -414,6 +414,7 @@ static Eterm add_stacktrace(Process* c_p, Eterm Value, Eterm exc); static void save_stacktrace(Process* c_p, BeamInstr* pc, Eterm* reg, ErtsCodeMFA *bif_mfa, Eterm args); static struct StackTrace * get_trace_from_exc(Eterm exc); +static Eterm *get_freason_ptr_from_exc(Eterm exc); static Eterm make_arglist(Process* c_p, Eterm* reg, int a); void @@ -1902,6 +1903,25 @@ static int is_raised_exc(Eterm exc) { } } +static Eterm *get_freason_ptr_from_exc(Eterm exc) { + static Eterm dummy_freason; + struct StackTrace* s; + + if (exc == NIL) { + /* + * Is is not exactly clear when exc can be NIL. Probably only + * when the exception has been generated from native code. + * Return a pointer to an Eterm that can be safely written and + * ignored. + */ + return &dummy_freason; + } else { + ASSERT(is_list(exc)); + s = (struct StackTrace *) big_val(CDR(list_val(exc))); + return &s->freason; + } +} + /* * Creating a list with the argument registers */ diff --git a/erts/emulator/beam/instrs.tab b/erts/emulator/beam/instrs.tab index 462ee77e6f..7cffe7fb5c 100644 --- a/erts/emulator/beam/instrs.tab +++ b/erts/emulator/beam/instrs.tab @@ -1064,19 +1064,30 @@ raw_raise() { Eterm class = x(0); Eterm value = x(1); Eterm stacktrace = x(2); + Eterm* freason_ptr; + + /* + * Note that the i_raise instruction will override c_p->freason + * with the freason field stored inside the StackTrace struct in + * ftrace. Therefore, we must take care to store the class both + * inside the StackTrace struct and in c_p->freason (important if + * the class is different from the class of the original + * exception). + */ + freason_ptr = get_freason_ptr_from_exc(stacktrace); if (class == am_error) { - c_p->freason = EXC_ERROR & ~EXF_SAVETRACE; + *freason_ptr = c_p->freason = EXC_ERROR & ~EXF_SAVETRACE; c_p->fvalue = value; c_p->ftrace = stacktrace; goto find_func_info; } else if (class == am_exit) { - c_p->freason = EXC_EXIT & ~EXF_SAVETRACE; + *freason_ptr = c_p->freason = EXC_EXIT & ~EXF_SAVETRACE; c_p->fvalue = value; c_p->ftrace = stacktrace; goto find_func_info; } else if (class == am_throw) { - c_p->freason = EXC_THROWN & ~EXF_SAVETRACE; + *freason_ptr = c_p->freason = EXC_THROWN & ~EXF_SAVETRACE; c_p->fvalue = value; c_p->ftrace = stacktrace; goto find_func_info; |