aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/stdlib/src/gen_statem.erl76
1 files changed, 53 insertions, 23 deletions
diff --git a/lib/stdlib/src/gen_statem.erl b/lib/stdlib/src/gen_statem.erl
index e6bb38fc2c..782e027b29 100644
--- a/lib/stdlib/src/gen_statem.erl
+++ b/lib/stdlib/src/gen_statem.erl
@@ -217,6 +217,22 @@ event_type(Type) ->
false
end.
+
+
+-define(
+ STACKTRACE(),
+ try throw(ok) catch _ -> erlang:get_stacktrace() end).
+
+-define(
+ TERMINATE(Reason, Debug, S, Q),
+ terminate(
+ exit,
+ begin Reason end,
+ ?STACKTRACE(),
+ begin Debug end,
+ begin S end,
+ begin Q end)).
+
%%%==========================================================================
%%% API
@@ -455,7 +471,7 @@ enter(Module, Options, State, StateData, Server, InitOps, Parent) ->
State, StateData,
[{retry,false}|StateOps]);
[Reason] ->
- terminate(Reason, Debug, S, [])
+ ?TERMINATE(Reason, Debug, S, [])
end.
%%%==========================================================================
@@ -510,7 +526,7 @@ system_continue(Parent, Debug, S) ->
loop(Parent, Debug, S).
system_terminate(Reason, _Parent, Debug, S) ->
- terminate(Reason, Debug, S, []).
+ ?TERMINATE(Reason, Debug, S, []).
system_code_change(
#{module := Module,
@@ -646,7 +662,7 @@ loop_receive(Parent, Debug, #{timer := Timer} = S) ->
%% EXIT is not a 2-tuple and therefore
%% not an event and has no event_type(),
%% but this will stand out in the crash report...
- terminate(Reason, Debug, S, [EXIT]);
+ ?TERMINATE(Reason, Debug, S, [EXIT]);
{timeout,Timer,Content} when Timer =/= undefined ->
loop_receive(
Parent, Debug, S, {timeout,Content}, undefined);
@@ -727,7 +743,7 @@ loop_events(
loop_event_result(Parent, Debug, S, Events, Event, Result) ->
case Result of
{stop,Reason,NewStateData} ->
- terminate(
+ ?TERMINATE(
Reason, Debug,
S#{state_data := NewStateData},
[Event|Events]);
@@ -742,9 +758,10 @@ loop_event_result(Parent, Debug, S, Events, Event, Result) ->
[Reply]
end,
BadReplies =
- reply_then_terminate(Reason, Debug, NewS, Q, Replies),
+ reply_then_terminate(
+ exit, Reason, ?STACKTRACE(), Debug, NewS, Q, Replies),
%% Since we got back here Replies was bad
- terminate(
+ ?TERMINATE(
{bad_return_value,{stop,Reason,BadReplies,NewStateData}},
Debug, NewS, Q);
{next_state,NewState,NewStateData} ->
@@ -757,7 +774,7 @@ loop_event_result(Parent, Debug, S, Events, Event, Result) ->
Parent, Debug, S, Events, Event,
NewState, NewStateData, StateOps);
_ ->
- terminate(
+ ?TERMINATE(
{bad_return_value,Result}, Debug, S, [Event|Events])
end.
@@ -815,14 +832,14 @@ loop_event_state_ops(
postponed := P},
Q, Timer);
[Reason,Debug] ->
- terminate(Reason, Debug, S, [Event|Events]);
+ ?TERMINATE(Reason, Debug, S, [Event|Events]);
[Class,Reason,Stacktrace,Debug] ->
terminate(
Class, Reason, Stacktrace, Debug, S, [Event|Events])
end;
%%
[Reason] ->
- terminate(Reason, Debug0, S, [Event|Events])
+ ?TERMINATE(Reason, Debug0, S, [Event|Events])
end.
%%---------------------------------------------------------------------------
@@ -921,13 +938,15 @@ process_state_operations([Operation|Operations] = OOs, Debug, S, Q, P) ->
end
end.
-reply_then_terminate(Reason, Debug, S, Q, []) ->
- terminate(Reason, Debug, S, Q);
-reply_then_terminate(Reason, Debug, S, Q, [R|Rs] = RRs) ->
+reply_then_terminate(Class, Reason, Stacktrace, Debug, S, Q, []) ->
+ terminate(Class, Reason, Stacktrace, Debug, S, Q);
+reply_then_terminate(
+ Class, Reason, Stacktrace, Debug, S, Q, [R|Rs] = RRs) ->
case R of
{reply,{_To,_Tag}=Client,Reply} ->
NewDebug = do_reply(Debug, S, Client, Reply),
- reply_then_terminate(Reason, NewDebug, S, Q, Rs);
+ reply_then_terminate(
+ Class, Reason, Stacktrace, NewDebug, S, Q, Rs);
_ ->
RRs % bad_return_value
end.
@@ -1034,12 +1053,9 @@ cancel_timer(TimerRef) ->
end.
-terminate(Reason, Debug, S, Q) ->
- terminate(exit, Reason, [], Debug, S, Q).
-%%
terminate(
Class, Reason, Stacktrace, Debug,
- #{name := Name, module := Module,
+ #{module := Module,
state := State, state_data := StateData} = S,
Q) ->
try Module:terminate(Reason, State, StateData) of
@@ -1049,7 +1065,7 @@ terminate(
C:R ->
ST = erlang:get_stacktrace(),
error_info(
- C, R, ST, Debug, Name, Q,
+ C, R, ST, Debug, S, Q,
format_status(terminate, get(), S)),
erlang:raise(C, R, ST)
end,
@@ -1059,7 +1075,7 @@ terminate(
{shutdown,_} -> ok;
_ ->
error_info(
- Class, Reason, Stacktrace, Debug, Name, Q,
+ Class, Reason, Stacktrace, Debug, S, Q,
format_status(terminate, get(), S))
end,
case Stacktrace of
@@ -1070,7 +1086,10 @@ terminate(
end.
error_info(
- Class, Reason, Stacktrace, Debug, Name, Q, FmtStateData) ->
+ Class, Reason, Stacktrace, Debug,
+ #{name := Name, callback_mode := CallbackMode,
+ state := State, postponed := P},
+ Q, FmtStateData) ->
{FixedReason,FixedStacktrace} =
case Stacktrace of
[{M,F,Args,_}|ST]
@@ -1079,7 +1098,13 @@ error_info(
false ->
{{'module could not be loaded',M},ST};
_ ->
- Arity = length(Args),
+ Arity =
+ if
+ is_list(Args) ->
+ length(Args);
+ is_integer(Args) ->
+ Args
+ end,
case erlang:function_exported(M, F, Arity) of
true ->
{Reason,Stacktrace};
@@ -1100,6 +1125,9 @@ error_info(
end ++
"** When Server state = ~p~n" ++
"** Reason for termination = ~w:~p~n" ++
+ "** State = ~p~n" ++
+ "** Callback mode = ~p~n" ++
+ "** Queued/Posponed = ~w/~w~n" ++
case FixedStacktrace of
[] ->
"";
@@ -1110,10 +1138,12 @@ error_info(
[Name |
case Q of
[] ->
- [FmtStateData,Class,FixedReason];
+ [];
[Event|_] ->
- [Event,FmtStateData,Class,FixedReason]
+ [Event]
end] ++
+ [FmtStateData,Class,FixedReason,
+ State,CallbackMode,length(Q),length(P)] ++
case FixedStacktrace of
[] ->
[];