aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2017-12-08 10:40:55 +0100
committerGitHub <[email protected]>2017-12-08 10:40:55 +0100
commit70c5dccad3d839a455682e22ac187e325c792112 (patch)
tree2e507e879306ee5dc89d270b69f87fac76e6a5eb /erts
parent842d3c0be0d2095c8d1e79ea3d672e191f7f954e (diff)
parent9dce8fe582cecb586375dafff4b84c11a1b3ac7e (diff)
downloadotp-70c5dccad3d839a455682e22ac187e325c792112.tar.gz
otp-70c5dccad3d839a455682e22ac187e325c792112.tar.bz2
otp-70c5dccad3d839a455682e22ac187e325c792112.zip
Merge pull request #1634 from bjorng/bjorn/get_stacktrace-syntax/OTP-14692
Add syntax in try/catch to retrieve the stacktrace directly
Diffstat (limited to 'erts')
-rw-r--r--erts/doc/src/erlang.xml45
-rw-r--r--erts/emulator/beam/instrs.tab5
-rw-r--r--erts/emulator/beam/ops.tab6
-rw-r--r--erts/emulator/hipe/hipe_bif2.c5
-rw-r--r--erts/emulator/hipe/hipe_bif2.tab1
-rw-r--r--erts/emulator/hipe/hipe_bif_list.m41
-rw-r--r--erts/emulator/hipe/hipe_native_bif.h3
-rw-r--r--erts/emulator/hipe/hipe_primops.h1
-rw-r--r--erts/emulator/test/binary_SUITE.erl4
-rw-r--r--erts/emulator/test/call_trace_SUITE.erl4
-rw-r--r--erts/emulator/test/dirty_bif_SUITE.erl65
-rw-r--r--erts/emulator/test/dirty_nif_SUITE.erl14
-rw-r--r--erts/emulator/test/driver_SUITE.erl4
-rw-r--r--erts/emulator/test/exception_SUITE.erl4
-rw-r--r--erts/emulator/test/nif_SUITE.erl9
15 files changed, 82 insertions, 89 deletions
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index daf3002ec7..d7404fa3ce 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -1985,39 +1985,26 @@ true</pre>
<fsummary>Get the call stack back-trace of the last exception.</fsummary>
<type name="stack_item"/>
<desc>
- <p>Gets the call stack back-trace (<em>stacktrace</em>) for an
- exception that has just been caught
- in the calling process as a list of
- <c>{<anno>Module</anno>,<anno>Function</anno>,<anno>Arity</anno>,<anno>Location</anno>}</c>
- tuples. Field <c><anno>Arity</anno></c> in the first tuple can be the
- argument list of that function call instead of an arity integer,
- depending on the exception.</p>
- <p>If there has not been any exceptions in a process, the
- stacktrace is <c>[]</c>. After a code change for the process,
- the stacktrace can also be reset to <c>[]</c>.</p>
- <p><c>erlang:get_stacktrace/0</c> is only guaranteed to return
- a stacktrace if called (directly or indirectly) from within the
- scope of a <c>try</c> expression. That is, the following call works:</p>
+ <warning><p><c>erlang:get_stacktrace/0</c> is deprecated and will stop working
+ in a future release.</p></warning>
+ <p>Instead of using <c>erlang:get_stacktrace/0</c> to retrieve
+ the call stack back-trace, use the following syntax:</p>
<pre>
try Expr
catch
- C:R ->
- {C,R,erlang:get_stacktrace()}
+ Class:Reason:Stacktrace ->
+ {Class,Reason,Stacktrace}
end</pre>
- <p>As does this call:</p>
-<pre>
-try Expr
-catch
- C:R ->
- {C,R,helper()}
-end
-
-helper() ->
- erlang:get_stacktrace().</pre>
-
- <warning><p>In a future release,
- <c>erlang:get_stacktrace/0</c> will return <c>[]</c> if called
- from outside a <c>try</c> expression.</p></warning>
+ <p><c>erlang:get_stacktrace/0</c> retrieves the call stack back-trace
+ (<em>stacktrace</em>) for an exception that has just been
+ caught in the calling process as a list of
+ <c>{<anno>Module</anno>,<anno>Function</anno>,<anno>Arity</anno>,<anno>Location</anno>}</c>
+ tuples. Field <c><anno>Arity</anno></c> in the first tuple can
+ be the argument list of that function call instead of an arity
+ integer, depending on the exception.</p>
+ <p>If there has not been any exceptions in a process, the
+ stacktrace is <c>[]</c>. After a code change for the process,
+ the stacktrace can also be reset to <c>[]</c>.</p>
<p>The stacktrace is the same data as operator <c>catch</c>
returns, for example:</p>
<pre>
diff --git a/erts/emulator/beam/instrs.tab b/erts/emulator/beam/instrs.tab
index d934abb217..b92152238e 100644
--- a/erts/emulator/beam/instrs.tab
+++ b/erts/emulator/beam/instrs.tab
@@ -931,3 +931,8 @@ i_raise() {
//| -no_next
}
+build_stacktrace() {
+ SWAPOUT;
+ x(0) = build_stacktrace(c_p, x(0));
+ SWAPIN;
+}
diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab
index c30af029ce..fd1b3b9c74 100644
--- a/erts/emulator/beam/ops.tab
+++ b/erts/emulator/beam/ops.tab
@@ -1578,3 +1578,9 @@ i_recv_mark
recv_set Fail | label Lbl | loop_rec Lf Reg => \
i_recv_set | label Lbl | loop_rec Lf Reg
i_recv_set
+
+#
+# OTP 21.
+#
+
+build_stacktrace
diff --git a/erts/emulator/hipe/hipe_bif2.c b/erts/emulator/hipe/hipe_bif2.c
index 9ebbb22846..df377b2153 100644
--- a/erts/emulator/hipe/hipe_bif2.c
+++ b/erts/emulator/hipe/hipe_bif2.c
@@ -190,3 +190,8 @@ BIF_RETTYPE hipe_bifs_llvm_fix_pinned_regs_0(BIF_ALIST_0)
{
BIF_RET(am_ok);
}
+
+BIF_RETTYPE hipe_bifs_build_stacktrace_1(BIF_ALIST_1)
+{
+ BIF_RET(build_stacktrace(BIF_P, BIF_ARG_1));
+}
diff --git a/erts/emulator/hipe/hipe_bif2.tab b/erts/emulator/hipe/hipe_bif2.tab
index bbcb577be0..c4da44606a 100644
--- a/erts/emulator/hipe/hipe_bif2.tab
+++ b/erts/emulator/hipe/hipe_bif2.tab
@@ -32,3 +32,4 @@ bif hipe_bifs:modeswitch_debug_on/0
bif hipe_bifs:modeswitch_debug_off/0
bif hipe_bifs:debug_native_called/2
bif hipe_bifs:llvm_fix_pinned_regs/0
+bif hipe_bifs:build_stacktrace/1
diff --git a/erts/emulator/hipe/hipe_bif_list.m4 b/erts/emulator/hipe/hipe_bif_list.m4
index 625d8486fd..4f0a655508 100644
--- a/erts/emulator/hipe/hipe_bif_list.m4
+++ b/erts/emulator/hipe/hipe_bif_list.m4
@@ -186,6 +186,7 @@ gc_bif_interface_1(nbif_erase_1, erase_1)
gc_bif_interface_1(nbif_erts_internal_garbage_collect_1, erts_internal_garbage_collect_1)
gc_nofail_primop_interface_1(nbif_gc_1, hipe_gc)
gc_bif_interface_2(nbif_put_2, put_2)
+gc_bif_interface_2(nbif_hipe_bifs_build_stacktrace, hipe_bifs_build_stacktrace_1)
/*
* Debug BIFs that need read access to the full state.
diff --git a/erts/emulator/hipe/hipe_native_bif.h b/erts/emulator/hipe/hipe_native_bif.h
index d5081b8438..6dffec1d8d 100644
--- a/erts/emulator/hipe/hipe_native_bif.h
+++ b/erts/emulator/hipe/hipe_native_bif.h
@@ -104,6 +104,9 @@ void hipe_emulate_fpe(Process*);
AEXTERN(void,nbif_emasculate_binary,(Eterm));
void hipe_emasculate_binary(Eterm);
+AEXTERN(BIF_RETTYPE,nbif_hipe_bifs_build_stacktrace,(Process*,Eterm));
+BIF_RETTYPE hipe_bifs_build_stacktrace_1(BIF_ALIST_1);
+
/*
* Stuff that is different in SMP and non-SMP.
*/
diff --git a/erts/emulator/hipe/hipe_primops.h b/erts/emulator/hipe/hipe_primops.h
index a6abd3e011..d6fd10bdff 100644
--- a/erts/emulator/hipe/hipe_primops.h
+++ b/erts/emulator/hipe/hipe_primops.h
@@ -83,6 +83,7 @@ PRIMOP_LIST(am_emulate_fpe, &nbif_emulate_fpe)
#endif
PRIMOP_LIST(am_emasculate_binary, &nbif_emasculate_binary)
PRIMOP_LIST(am_debug_native_called, &nbif_hipe_bifs_debug_native_called)
+PRIMOP_LIST(am_build_stacktrace, &nbif_hipe_bifs_build_stacktrace)
#if defined(__sparc__)
#include "hipe_sparc_primops.h"
diff --git a/erts/emulator/test/binary_SUITE.erl b/erts/emulator/test/binary_SUITE.erl
index c71267a6d1..4bc1838139 100644
--- a/erts/emulator/test/binary_SUITE.erl
+++ b/erts/emulator/test/binary_SUITE.erl
@@ -1472,13 +1472,13 @@ error_after_yield(Type, M, F, AN, AFun, TrapFunc) ->
apply(M, F, A),
exit({unexpected_success, {M, F, A}})
catch
- error:Type ->
+ error:Type:Stk ->
erlang:trace(self(),false,[running,{tracer,Tracer}]),
%% We threw the exception from the native
%% function we trapped to, but we want
%% the BIF that originally was called
%% to appear in the stack trace.
- [{M, F, A, _} | _] = erlang:get_stacktrace()
+ [{M, F, A, _} | _] = Stk
end
end),
receive
diff --git a/erts/emulator/test/call_trace_SUITE.erl b/erts/emulator/test/call_trace_SUITE.erl
index 1251d644ae..d19f7f81ad 100644
--- a/erts/emulator/test/call_trace_SUITE.erl
+++ b/erts/emulator/test/call_trace_SUITE.erl
@@ -1116,8 +1116,8 @@ get_deep_4_loc(Arg) ->
deep_4(Arg),
ct:fail(should_not_return_to_here)
catch
- _:_ ->
- [{?MODULE,deep_4,1,Loc0}|_] = erlang:get_stacktrace(),
+ _:_:Stk ->
+ [{?MODULE,deep_4,1,Loc0}|_] = Stk,
Loc0
end.
diff --git a/erts/emulator/test/dirty_bif_SUITE.erl b/erts/emulator/test/dirty_bif_SUITE.erl
index c8f0cbf42d..46eb0cba58 100644
--- a/erts/emulator/test/dirty_bif_SUITE.erl
+++ b/erts/emulator/test/dirty_bif_SUITE.erl
@@ -108,90 +108,80 @@ dirty_bif_exception(Config) when is_list(Config) ->
erts_debug:dirty_cpu(error, Error),
ct:fail(expected_exception)
catch
- error:ErrorType ->
- [{erts_debug,dirty_cpu,[error, Error],_}|_]
- = erlang:get_stacktrace(),
+ error:ErrorType:Stk1 ->
+ [{erts_debug,dirty_cpu,[error, Error],_}|_] = Stk1,
ok
end,
try
apply(erts_debug,dirty_cpu,[error, Error]),
ct:fail(expected_exception)
catch
- error:ErrorType ->
- [{erts_debug,dirty_cpu,[error, Error],_}|_]
- = erlang:get_stacktrace(),
+ error:ErrorType:Stk2 ->
+ [{erts_debug,dirty_cpu,[error, Error],_}|_] = Stk2,
ok
end,
try
erts_debug:dirty_io(error, Error),
ct:fail(expected_exception)
catch
- error:ErrorType ->
- [{erts_debug,dirty_io,[error, Error],_}|_]
- = erlang:get_stacktrace(),
+ error:ErrorType:Stk3 ->
+ [{erts_debug,dirty_io,[error, Error],_}|_] = Stk3,
ok
end,
try
apply(erts_debug,dirty_io,[error, Error]),
ct:fail(expected_exception)
catch
- error:ErrorType ->
- [{erts_debug,dirty_io,[error, Error],_}|_]
- = erlang:get_stacktrace(),
+ error:ErrorType:Stk4 ->
+ [{erts_debug,dirty_io,[error, Error],_}|_] = Stk4,
ok
end,
try
erts_debug:dirty(normal, error, Error),
ct:fail(expected_exception)
catch
- error:ErrorType ->
- [{erts_debug,dirty,[normal, error, Error],_}|_]
- = erlang:get_stacktrace(),
+ error:ErrorType:Stk5 ->
+ [{erts_debug,dirty,[normal, error, Error],_}|_] = Stk5,
ok
end,
try
apply(erts_debug,dirty,[normal, error, Error]),
ct:fail(expected_exception)
catch
- error:ErrorType ->
- [{erts_debug,dirty,[normal, error, Error],_}|_]
- = erlang:get_stacktrace(),
+ error:ErrorType:Stk6 ->
+ [{erts_debug,dirty,[normal, error, Error],_}|_] = Stk6,
ok
end,
try
erts_debug:dirty(dirty_cpu, error, Error),
ct:fail(expected_exception)
catch
- error:ErrorType ->
- [{erts_debug,dirty,[dirty_cpu, error, Error],_}|_]
- = erlang:get_stacktrace(),
+ error:ErrorType:Stk7 ->
+ [{erts_debug,dirty,[dirty_cpu, error, Error],_}|_] = Stk7,
ok
end,
try
apply(erts_debug,dirty,[dirty_cpu, error, Error]),
ct:fail(expected_exception)
catch
- error:ErrorType ->
- [{erts_debug,dirty,[dirty_cpu, error, Error],_}|_]
- = erlang:get_stacktrace(),
+ error:ErrorType:Stk8 ->
+ [{erts_debug,dirty,[dirty_cpu, error, Error],_}|_] = Stk8,
ok
end,
try
erts_debug:dirty(dirty_io, error, Error),
ct:fail(expected_exception)
catch
- error:ErrorType ->
- [{erts_debug,dirty,[dirty_io, error, Error],_}|_]
- = erlang:get_stacktrace(),
+ error:ErrorType:Stk9 ->
+ [{erts_debug,dirty,[dirty_io, error, Error],_}|_] = Stk9,
ok
end,
try
apply(erts_debug,dirty,[dirty_io, error, Error]),
ct:fail(expected_exception)
catch
- error:ErrorType ->
- [{erts_debug,dirty,[dirty_io, error, Error],_}|_]
- = erlang:get_stacktrace(),
+ error:ErrorType:Stk10 ->
+ [{erts_debug,dirty,[dirty_io, error, Error],_}|_] = Stk10,
ok
end
end,
@@ -204,25 +194,22 @@ dirty_bif_multischedule_exception(Config) when is_list(Config) ->
try
erts_debug:dirty_cpu(reschedule,1001)
catch
- error:badarg ->
- [{erts_debug,dirty_cpu,[reschedule, 1001],_}|_]
- = erlang:get_stacktrace(),
+ error:badarg:Stk1 ->
+ [{erts_debug,dirty_cpu,[reschedule, 1001],_}|_] = Stk1,
ok
end,
try
erts_debug:dirty_io(reschedule,1001)
catch
- error:badarg ->
- [{erts_debug,dirty_io,[reschedule, 1001],_}|_]
- = erlang:get_stacktrace(),
+ error:badarg:Stk2 ->
+ [{erts_debug,dirty_io,[reschedule, 1001],_}|_] = Stk2,
ok
end,
try
erts_debug:dirty(normal,reschedule,1001)
catch
- error:badarg ->
- [{erts_debug,dirty,[normal,reschedule,1001],_}|_]
- = erlang:get_stacktrace(),
+ error:badarg:Stk3 ->
+ [{erts_debug,dirty,[normal,reschedule,1001],_}|_] = Stk3,
ok
end.
diff --git a/erts/emulator/test/dirty_nif_SUITE.erl b/erts/emulator/test/dirty_nif_SUITE.erl
index d36113c3e3..93d0ac392c 100644
--- a/erts/emulator/test/dirty_nif_SUITE.erl
+++ b/erts/emulator/test/dirty_nif_SUITE.erl
@@ -109,9 +109,8 @@ dirty_nif_exception(Config) when is_list(Config) ->
call_dirty_nif_exception(1),
ct:fail(expected_badarg)
catch
- error:badarg ->
- [{?MODULE,call_dirty_nif_exception,[1],_}|_] =
- erlang:get_stacktrace(),
+ error:badarg:Stk1 ->
+ [{?MODULE,call_dirty_nif_exception,[1],_}|_] = Stk1,
ok
end,
try
@@ -121,9 +120,8 @@ dirty_nif_exception(Config) when is_list(Config) ->
call_dirty_nif_exception(0),
ct:fail(expected_badarg)
catch
- error:badarg ->
- [{?MODULE,call_dirty_nif_exception,[0],_}|_] =
- erlang:get_stacktrace(),
+ error:badarg:Stk2 ->
+ [{?MODULE,call_dirty_nif_exception,[0],_}|_] = Stk2,
ok
end,
%% this checks that a dirty NIF can raise various terms as
@@ -138,8 +136,8 @@ nif_raise_exceptions(NifFunc) ->
erlang:apply(?MODULE,NifFunc,[Term]),
ct:fail({expected,Term})
catch
- error:Term ->
- [{?MODULE,NifFunc,[Term],_}|_] = erlang:get_stacktrace(),
+ error:Term:Stk ->
+ [{?MODULE,NifFunc,[Term],_}|_] = Stk,
ok
end
end, ok, ExcTerms).
diff --git a/erts/emulator/test/driver_SUITE.erl b/erts/emulator/test/driver_SUITE.erl
index 475e03087a..6446d5f6d2 100644
--- a/erts/emulator/test/driver_SUITE.erl
+++ b/erts/emulator/test/driver_SUITE.erl
@@ -2614,8 +2614,8 @@ rpc(Config, Fun) ->
Result
= try Fun() of
Res -> Res
- catch E:R ->
- {'EXIT',E,R,erlang:get_stacktrace()}
+ catch E:R:Stk ->
+ {'EXIT',E,R,Stk}
end,
Self ! {Ref, Result}
end),
diff --git a/erts/emulator/test/exception_SUITE.erl b/erts/emulator/test/exception_SUITE.erl
index be9b63d534..da0292f385 100644
--- a/erts/emulator/test/exception_SUITE.erl
+++ b/erts/emulator/test/exception_SUITE.erl
@@ -395,12 +395,12 @@ raise(Conf) when is_list(Conf) ->
try
try foo({'div',{1,0}})
catch
- error:badarith ->
+ error:badarith:A0 ->
put(raise, A0 = erlang:get_stacktrace()),
erlang:raise(error, badarith, A0)
end
catch
- error:badarith ->
+ error:badarith:A1 ->
A1 = erlang:get_stacktrace(),
A1 = get(raise)
end,
diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl
index 2afeb7e4cf..85c302e310 100644
--- a/erts/emulator/test/nif_SUITE.erl
+++ b/erts/emulator/test/nif_SUITE.erl
@@ -2257,9 +2257,8 @@ nif_schedule(Config) when is_list(Config) ->
{B,A} = call_nif_schedule(A, B),
ok = try call_nif_schedule(1, 2)
catch
- error:badarg ->
- [{?MODULE,call_nif_schedule,[1,2],_}|_] =
- erlang:get_stacktrace(),
+ error:badarg:Stk ->
+ [{?MODULE,call_nif_schedule,[1,2],_}|_] = Stk,
ok
end,
ok.
@@ -2429,8 +2428,8 @@ nif_raise_exceptions(NifFunc) ->
erlang:apply(?MODULE,NifFunc,[Term]),
ct:fail({expected,Term})
catch
- error:Term ->
- [{?MODULE,NifFunc,[Term],_}|_] = erlang:get_stacktrace(),
+ error:Term:Stk ->
+ [{?MODULE,NifFunc,[Term],_}|_] = Stk,
ok
end
end, ok, ExcTerms).