mirror of
https://github.com/processone/ejabberd.git
synced 2024-12-26 17:38:45 +01:00
Allow customizing the StateData in p1_fsm before error reporting.
A new callback is introduced on the p1_fsm behaviour:
print_error/1
If the module implements this function, it will be invoked
in case of process crash with the current state data *before*
printing the error in the log. The function must return the
desired State to print.
It is used in ejabberd_c2s to prune the presence sets that
can be large. Instead, the state is changed to include only
the # of elements on each set.
Change inspired in comming changes to gen_server on OTP, and
b01d15abc3 (diff-0)
This commit is contained in:
parent
44b282474a
commit
41aa693896
@ -55,7 +55,9 @@
|
||||
handle_sync_event/4,
|
||||
code_change/4,
|
||||
handle_info/3,
|
||||
terminate/3]).
|
||||
terminate/3,
|
||||
print_state/1
|
||||
]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("jlib.hrl").
|
||||
@ -1334,6 +1336,19 @@ handle_info(Info, StateName, StateData) ->
|
||||
?ERROR_MSG("Unexpected info: ~p", [Info]),
|
||||
fsm_next_state(StateName, StateData).
|
||||
|
||||
|
||||
%%----------------------------------------------------------------------
|
||||
%% Func: print_state/1
|
||||
%% Purpose: Prepare the state to be printed on error log
|
||||
%% Returns: State to print
|
||||
%%----------------------------------------------------------------------
|
||||
print_state(State = #state{pres_t = T, pres_f = F, pres_a = A, pres_i = I}) ->
|
||||
State#state{pres_t = {pres_t, ?SETS:size(T)},
|
||||
pres_f = {pres_f, ?SETS:size(F)},
|
||||
pres_a = {pres_a, ?SETS:size(A)},
|
||||
pres_i = {pres_i, ?SETS:size(I)}
|
||||
}.
|
||||
|
||||
%%----------------------------------------------------------------------
|
||||
%% Func: terminate/3
|
||||
%% Purpose: Shutdown the fsm
|
||||
|
@ -25,7 +25,8 @@
|
||||
%% - You can limit the time processing a message (TODO): If the
|
||||
%% message processing does not return in a given period of time, the
|
||||
%% process will be terminated.
|
||||
%%
|
||||
%% - You might customize the State data before sending it to error_logger
|
||||
%% in case of a crash (just export the function print_state/1)
|
||||
%% $Id$
|
||||
%%
|
||||
-module(p1_fsm).
|
||||
@ -146,7 +147,7 @@
|
||||
|
||||
behaviour_info(callbacks) ->
|
||||
[{init,1},{handle_event,3},{handle_sync_event,4},{handle_info,3},
|
||||
{terminate,3},{code_change,4}];
|
||||
{terminate,3},{code_change,4}, {print_state,1}];
|
||||
behaviour_info(_Other) ->
|
||||
undefined.
|
||||
|
||||
@ -376,7 +377,7 @@ loop(Parent, Name, StateName, StateData, Mod, hibernate, Debug,
|
||||
Debug, Limits, Queue1, QueueLen - 1, false);
|
||||
{empty, _} ->
|
||||
Reason = internal_queue_error,
|
||||
error_info(Reason, Name, hibernate, StateName, StateData, Debug),
|
||||
error_info(Mod, Reason, Name, hibernate, StateName, StateData, Debug),
|
||||
exit(Reason)
|
||||
end;
|
||||
loop(Parent, Name, StateName, StateData, Mod, hibernate, Debug,
|
||||
@ -620,7 +621,7 @@ reply(Name, {To, Tag}, Reply, Debug, StateName) ->
|
||||
terminate(Reason, Name, Msg, Mod, StateName, StateData, Debug) ->
|
||||
case catch Mod:terminate(Reason, StateName, StateData) of
|
||||
{'EXIT', R} ->
|
||||
error_info(R, Name, Msg, StateName, StateData, Debug),
|
||||
error_info(Mod, R, Name, Msg, StateName, StateData, Debug),
|
||||
exit(R);
|
||||
_ ->
|
||||
case Reason of
|
||||
@ -639,12 +640,12 @@ terminate(Reason, Name, Msg, Mod, StateName, StateData, Debug) ->
|
||||
[self(), Limit]),
|
||||
exit(shutdown);
|
||||
_ ->
|
||||
error_info(Reason, Name, Msg, StateName, StateData, Debug),
|
||||
error_info(Mod, Reason, Name, Msg, StateName, StateData, Debug),
|
||||
exit(Reason)
|
||||
end
|
||||
end.
|
||||
|
||||
error_info(Reason, Name, Msg, StateName, StateData, Debug) ->
|
||||
error_info(Mod, Reason, Name, Msg, StateName, StateData, Debug) ->
|
||||
Reason1 =
|
||||
case Reason of
|
||||
{undef,[{M,F,A}|MFAs]} ->
|
||||
@ -662,12 +663,16 @@ error_info(Reason, Name, Msg, StateName, StateData, Debug) ->
|
||||
_ ->
|
||||
Reason
|
||||
end,
|
||||
StateToPrint = case erlang:function_exported(Mod, print_state, 1) of
|
||||
true -> (catch Mod:print_state(StateData));
|
||||
false -> StateData
|
||||
end,
|
||||
Str = "** State machine ~p terminating \n" ++
|
||||
get_msg_str(Msg) ++
|
||||
"** When State == ~p~n"
|
||||
"** Data == ~p~n"
|
||||
"** Reason for termination = ~n** ~p~n",
|
||||
format(Str, [Name, get_msg(Msg), StateName, StateData, Reason1]),
|
||||
format(Str, [Name, get_msg(Msg), StateName, StateToPrint, Reason1]),
|
||||
sys:print_log(Debug),
|
||||
ok.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user