aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPablo Polvorin <pablo.polvorin@process-one.net>2010-03-30 16:39:34 -0300
committerPablo Polvorin <pablo.polvorin@process-one.net>2010-03-30 16:39:34 -0300
commit41aa693896851a2a005a2487fca72d4a9e2aed3b (patch)
tree3ce27612a8b69d71a598387eef53804e7206264b /src
parentFix indentation (EJAB-1038) (diff)
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 http://github.com/erlyvideo/erlyvideo/commit/b01d15abc3189226dbf824db19db22da35fa33a0#diff-0
Diffstat (limited to 'src')
-rw-r--r--src/ejabberd_c2s.erl17
-rw-r--r--src/p1_fsm.erl19
2 files changed, 28 insertions, 8 deletions
diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl
index ef4614aa2..04a3fbcb1 100644
--- a/src/ejabberd_c2s.erl
+++ b/src/ejabberd_c2s.erl
@@ -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
diff --git a/src/p1_fsm.erl b/src/p1_fsm.erl
index 2ae2ed8ad..03ff7f8ce 100644
--- a/src/p1_fsm.erl
+++ b/src/p1_fsm.erl
@@ -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.