diff options
author | Pablo Polvorin <pablo.polvorin@process-one.net> | 2010-03-30 16:39:34 -0300 |
---|---|---|
committer | Pablo Polvorin <pablo.polvorin@process-one.net> | 2010-03-30 16:39:34 -0300 |
commit | 41aa693896851a2a005a2487fca72d4a9e2aed3b (patch) | |
tree | 3ce27612a8b69d71a598387eef53804e7206264b /src | |
parent | Fix 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.erl | 17 | ||||
-rw-r--r-- | src/p1_fsm.erl | 19 |
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. |