Ver código fonte

ft: gen_emm修改

master
SisMaker 4 anos atrás
pai
commit
372270cabe
1 arquivos alterados com 62 adições e 125 exclusões
  1. +62
    -125
      src/gen_emm.erl

+ 62
- 125
src/gen_emm.erl Ver arquivo

@ -50,9 +50,6 @@
sys:handle_debug(Debug, fun print_event/3, Name, Msg)
end).
-export_type([handler/0, handler_args/0, add_handler_ret/0,
del_handler_ret/0]).
-type epmHandler() ::
atom() |
{atom(), term()}.
@ -65,18 +62,14 @@
{stop, Reason :: term()} |
{error, {'EXIT', Reason :: term()}}.
-type handler() ::
atom() |
{atom(), term()}.
-type handler_args() ::
term().
-export_type([addEpmRet/0, delEpmRet/0]).
-type add_handler_ret() ::
-type addEpmRet() ::
ok |
term() |
{'EXIT', term()}.
-type del_handler_ret() ::
-type delEpmRet() ::
ok |
term() |
{'EXIT', term()}.
@ -259,7 +252,7 @@ info_notify(EpmSrv, Event) ->
call_notify(EpmSrv, Event) ->
epmRpc(EpmSrv, {'$syncNotify', Event}).
-spec call(serverRef(), handler(), term()) -> term().
-spec call(serverRef(), epmHandler(), term()) -> term().
call(EpmSrv, EpmHandler, Query) ->
epmRpc(EpmSrv, {'$epmCall', EpmHandler, Query}).
@ -322,10 +315,10 @@ epmRequest(EpmSrv, Cmd) ->
loopEntry(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, true) ->
proc_lib:hibernate(?MODULE, wakeupFromHib, [Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug]);
loopEntry(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, _) ->
loopEntry(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, _) ->
receiveIng(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, false).
wakeupFromHib(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug) ->
wakeupFromHib(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug) ->
receiveIng(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, true).
receiveIng(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, IsHib) ->
@ -333,13 +326,13 @@ receiveIng(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, IsHib) ->
{system, From, Req} ->
sys:handle_system_msg(Req, From, Parent, ?MODULE, Debug, {ServerName, HibernateAfterTimeout, EpmHers, IsHib}, IsHib);
{'EXIT', Parent, Reason} ->
terminate_server(Reason, Parent, ServerName, EpmHers);
terminate_server(Reason, Parent, ServerName, EpmHers);
{'$epm_call', From, Request} ->
epmCallMsg(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, From, Request);
epmCallMsg(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, From, Request);
{'$epm_info', CmdOrEmpHandler, Event} ->
epmInfoMsg(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, CmdOrEmpHandler, Event);
epmInfoMsg(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, CmdOrEmpHandler, Event);
Msg ->
handleMsg(Parent, ServerName, HibernateAfterTimeout,EpmHers, Debug, Msg)
handleMsg(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, Msg)
after HibernateAfterTimeout ->
proc_lib:hibernate(?MODULE, wakeupFromHib, [Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug])
end.
@ -386,7 +379,7 @@ epmInfoMsg(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, CmdOrEmpHa
{NewEpmHers, IsHib} = doNotify(EpmHers, handleEvent, Event, false),
loopEntry(Parent, ServerName, HibernateAfterTimeout, NewEpmHers, NewDebug, IsHib);
EpmHandler ->
{NewEpmHers, IsHib} = doEpmHandle(EpmHers, EpmHandler, handleInfo, Event, false),
{NewEpmHers, IsHib} = doEpmHandle(EpmHers, EpmHandler, handleInfo, Event, false),
loopEntry(Parent, ServerName, HibernateAfterTimeout, NewEpmHers, NewDebug, IsHib)
end.
@ -394,8 +387,7 @@ handleMsg(Parent, ServerName, HibernateAfterTimeout, EpmHers, Debug, Msg) ->
NewDebug = ?SYS_DEBUG(Debug, ServerName, {in, Msg}),
case Msg of
{'EXIT', From, Reason} ->
%% IMY-todo
NewEpmHers = epmStopOne(EpmHers, From),
NewEpmHers = epmStopOne(EpmHers, From, Reason),
receiveIng(Parent, ServerName, HibernateAfterTimeout, NewEpmHers, NewDebug, false);
{_From, Tag, stop} ->
try terminate_server(normal, Parent, EpmHers, ServerName)
@ -475,7 +467,7 @@ doSwapEpm(EpmHers, EpmId1, Args1, EpmMId, Args2) ->
_ ->
doAddSupEpm(NewEpmHers, EpmMId, {Args2, State2}, EpmSup)
end;
undefined ->
_ ->
doAddEpm(EpmHers, EpmMId, {Args2, undefined}, undefined)
end.
@ -485,7 +477,7 @@ doSwapSupEpm(EpmHers, EpmId1, Args1, EpmMId, Args2, EpmSup) ->
State2 = epmTerminate(EpmHer, Args1, swapped, {swapped, EpmMId, OldEpmSup}),
NewEpmHers = maps:remove(EpmId1, EpmHers),
doAddSupEpm(NewEpmHers, EpmMId, {Args2, State2}, EpmSup);
undefined ->
_ ->
doAddSupEpm(EpmHers, EpmMId, {Args2, undefined}, EpmSup)
end.
@ -526,7 +518,7 @@ doDelEpm(EpmHers, EpmHandler, Args) ->
#{EpmHandler := EpmHer} ->
epmTerminate(EpmHer, Args, delete, normal),
{ok, maps:remove(EpmHandler, EpmHers)};
undefined ->
_ ->
{{error, module_not_found}, EpmHers}
end.
@ -542,8 +534,8 @@ handleEpmCR(Result, EpmHers, EpmId, EpmHer, Event, From) ->
MewEpmHer = setelement(#epmHer.epmS, EpmHer, NewEpmS),
{EpmHers#{EpmId := MewEpmHer}, true};
{swapEpm, NewEpmS, Args1, EpmMId, Args2} ->
#epmHer{epmId = OldEpmMId, epmSup = EpmSup} = MewEpmHer = setelement(#epmHer.epmS, EpmHer, NewEpmS),
State = epmTerminate(MewEpmHer, Args1, swapped, {swapped, OldEpmMId, EpmSup}),
#epmHer{epmSup = EpmSup} = MewEpmHer = setelement(#epmHer.epmS, EpmHer, NewEpmS),
State = epmTerminate(MewEpmHer, Args1, swapped, {swapped, EpmMId, EpmSup}),
TemEpmHers = maps:remove(EpmId, EpmHers),
{_, NewEpmHers, IsHib} =
case EpmSup of
@ -555,8 +547,8 @@ handleEpmCR(Result, EpmHers, EpmId, EpmHer, Event, From) ->
{NewEpmHers, IsHib};
{swapEpm, Reply, NewEpmS, Args1, EpmMId, Args2} ->
reply(From, Reply),
#epmHer{epmId = OldEpmMId, epmSup = EpmSup} = MewEpmHer = setelement(#epmHer.epmS, EpmHer, NewEpmS),
State = epmTerminate(MewEpmHer, Args1, swapped, {swapped, OldEpmMId, EpmSup}),
#epmHer{epmSup = EpmSup} = MewEpmHer = setelement(#epmHer.epmS, EpmHer, NewEpmS),
State = epmTerminate(MewEpmHer, Args1, swapped, {swapped, EpmMId, EpmSup}),
TemEpmHers = maps:remove(EpmId, EpmHers),
{_, NewEpmHers, IsHib} =
case EpmSup of
@ -615,51 +607,22 @@ report_error(#epmHer{epmId = EpmId, epmM = EpmM}, Reason, State, LastIn) ->
handler => {EpmId, EpmM},
name => undefined,
last_message => LastIn,
state => State,
state => format_status(terminate, EpmM, get(), State),
reason => Reason
},
#{
domain => [otp],
report_cb => fun gen_emm:epm_log/1,
error_logger => #{tag => error}
report_cb => fun gen_emm:format_log/2,
error_logger => #{tag => error, report_cb => fun gen_event:format_log/1}
}).
epm_log(#{label := {gen_emm, epm_terminate}, handler := Handler, name := SName, last_message := LastIn, state := State, reason := Reason}) ->
Reason1 =
case Reason of
{'EXIT', {undef, [{M, F, A, L} | MFAs]}} ->
case code:is_loaded(M) of
false ->
{'module could not be loaded', [{M, F, A, L} | MFAs]};
_ ->
case erlang:function_exported(M, F, length(A)) of
true ->
{undef, [{M, F, A, L} | MFAs]};
false ->
{'function not exported', [{M, F, A, L} | MFAs]}
end
end;
{'EXIT', Why} ->
Why;
_ ->
Reason
end,
{"** gen_emm emp handler ~p crashed.~n"
"** Was installed in ~tp~n"
"** Last event was: ~tp~n"
"** When handler state == ~tp~n"
"** Reason == ~tp~n", [Handler, SName, LastIn, State, Reason1]};
epm_log(#{label := {gen_emm, no_handle_info}, module := Module, message := Msg}) ->
{"** Undefined handle_info in ~tp~n"
"** Unhandled message: ~tp~n", [Module, Msg]}.
epmStopAll(EpmHers) ->
forStopAll(maps:iterator(EpmHers)).
forStopAll(Iterator) ->
case maps:next(Iterator) of
{_K, V, NextIterator} ->
epmTerminate(V, stop, 'receive', shutdown),
epmTerminate(V, stop, stop, shutdown),
case element(#epmHer.epmSup, V) of
undefined ->
ignore;
@ -667,24 +630,24 @@ forStopAll(Iterator) ->
unlink(EpmSup)
end,
forStopAll(NextIterator);
none ->
_ ->
ok
end.
epmStopOne(ExitEmpSup, EpmHers) ->
forStopOne(maps:iterator(EpmHers), ExitEmpSup, EpmHers).
epmStopOne(ExitEmpSup, EpmHers, Reason) ->
forStopOne(maps:iterator(EpmHers), ExitEmpSup, Reason, EpmHers).
forStopOne(Iterator, ExitEmpSup, TemEpmHers) ->
forStopOne(Iterator, ExitEmpSup, Reason, TemEpmHers) ->
case maps:next(Iterator) of
{K, V, NextIterator} ->
case element(#epmHer.epmSup, V) =:= ExitEmpSup of
true ->
epmTerminate(V, stop, 'receive', shutdown),
forStopOne(NextIterator, ExitEmpSup, maps:remove(K, TemEpmHers));
epmTerminate(V, {stop, Reason}, {parent_terminated, {ExitEmpSup, Reason}}, shutdown),
forStopOne(NextIterator, ExitEmpSup, Reason, maps:remove(K, TemEpmHers));
_ ->
forStopOne(NextIterator, ExitEmpSup, TemEpmHers)
forStopOne(NextIterator, ExitEmpSup, Reason, TemEpmHers)
end;
none ->
_ ->
TemEpmHers
end.
@ -694,7 +657,7 @@ epmTerminate(#epmHer{epmM = EpmM, epmS = State} = EpmHer, Args, LastIn, Reason)
Res = (catch EpmM:terminate(Args, State)),
reportTerminate(EpmHer, Reason, Args, LastIn, Res),
Res;
false ->
_ ->
reportTerminate(EpmHer, Reason, Args, LastIn, ok),
ok
end.
@ -710,33 +673,15 @@ try_reply(false, _Msg) ->
ignore;
try_reply({To, Ref}, Msg) ->
try To ! {Ref, Msg},
ok
ok
catch _:_ ->
ok
end.
terminate_server(Reason, Parent, ServerName, EpmHers) ->
stop_handlers(EpmHers, ServerName),
do_unlink(Parent, EpmHers),
terminate_server(Reason, _Parent, _ServerName, EpmHers) ->
epmStopAll(EpmHers),
exit(Reason).
%% unlink the supervisor process of all supervised handlers.
%% We do not want a handler supervisor to EXIT due to the
%% termination of the event manager (server).
%% Do not unlink Parent !
do_unlink(Parent, MSL) ->
lists:foreach(fun(Handler) when Handler#handler.supervised =:= Parent ->
true;
(Handler) when is_pid(Handler#handler.supervised) ->
unlink(Handler#handler.supervised),
true;
(_) ->
true
end,
MSL).
%%-----------------------------------------------------------------
%% Callback functions for system messages handling.
%%-----------------------------------------------------------------
@ -762,7 +707,7 @@ forCodeChange(Iterator, CModule, OldVsn, Extra, TemEpmHers) ->
forCodeChange(NextIterator, CModule, OldVsn, Extra, TemEpmHers#{K := V#epmHer{epmS = NewEpmS}});
{_, _, NextIterator} ->
forCodeChange(NextIterator, CModule, OldVsn, Extra, TemEpmHers);
none ->
_ ->
TemEpmHers
end.
@ -773,7 +718,7 @@ forGetState(Iterator, Acc) ->
case maps:next(Iterator) of
{_K, #epmHer{epmId = EpmId, epmM = Module, epmS = EpmS}, NextIterator} ->
forGetState(NextIterator, [{Module, EpmId, EpmS} | Acc]);
none ->
_ ->
Acc
end.
@ -785,8 +730,8 @@ forReplaceState(Iterator, StateFun, TemEpmHers, NStates) ->
case maps:next(Iterator) of
{K, #epmHer{epmId = EpmId, epmM = Module, epmS = EpmS} = V, NextIterator} ->
NState = {_, _, NewEpmS} = StateFun({Module, EpmId, EpmS}),
forCodeChange(NextIterator, TemEpmHers#{K := V#epmHer{epmS = NewEpmS}}, [NState | NStates]);
none ->
forReplaceState(NextIterator, StateFun, TemEpmHers#{K := V#epmHer{epmS = NewEpmS}}, [NState | NStates]);
_ ->
{TemEpmHers, NStates}
end.
@ -797,7 +742,7 @@ forReplaceState(Iterator, StateFun, TemEpmHers, NStates) ->
print_event(Dev, Msg, Name) ->
case Msg of
{call, From, Request} ->
io:format(Dev, "*DBG* ~tp(~tp) got call ~tp from ~tp ~n", [Name, Request, From]);
io:format(Dev, "*DBG* ~tp got call ~tp from ~tp ~n", [Name, Request, From]);
{info, CmdOrEmpHandler, Event} ->
io:format(Dev, "*DBG* ~tp got info ~tp~n", [CmdOrEmpHandler, Event]);
{in, Msg} ->
@ -813,10 +758,12 @@ print_event(Dev, Msg, Name) ->
%% calls to error_logger prior to OTP-21.0.
format_log(Report) ->
Depth = error_logger:get_format_depth(),
FormatOpts = #{chars_limit => unlimited,
FormatOpts = #{
chars_limit => unlimited,
depth => Depth,
single_line => false,
encoding => utf8},
encoding => utf8
},
format_log_multi(limit_report(Report, Depth), FormatOpts).
limit_report(Report, unlimited) ->
@ -826,21 +773,23 @@ limit_report(#{label := {gen_event, terminate},
state := State,
reason := Reason} = Report,
Depth) ->
Report#{last_message => io_lib:limit_term(LastIn, Depth),
Report#{
last_message => io_lib:limit_term(LastIn, Depth),
state => io_lib:limit_term(State, Depth),
reason => io_lib:limit_term(Reason, Depth)};
limit_report(#{label := {gen_event, no_handle_info},
message := Msg} = Report,
Depth) ->
reason => io_lib:limit_term(Reason, Depth)
};
limit_report(#{label := {gen_event, no_handle_info}, message := Msg} = Report, Depth) ->
Report#{message => io_lib:limit_term(Msg, Depth)}.
%% format_log/2 is the report callback for any Logger handler, except
%% error_logger.
format_log(Report, FormatOpts0) ->
Default = #{chars_limit => unlimited,
Default = #{
chars_limit => unlimited,
depth => unlimited,
single_line => false,
encoding => utf8},
encoding => utf8
},
FormatOpts = maps:merge(Default, FormatOpts0),
IoOpts =
case FormatOpts of
@ -862,7 +811,7 @@ format_log_single(#{label := {gen_event, terminate},
P = p(FormatOpts),
Reason1 = fix_reason(Reason),
Format1 = lists:append(["Generic event handler ", P, " crashed. "
"Installed: ", P, ". Last event: ", P,
"Installed: ", P, ". Last event: ", P,
". State: ", P, ". Reason: ", P, "."]),
Args1 =
case Depth of
@ -878,8 +827,7 @@ format_log_single(#{label := {gen_event, no_handle_info},
message := Msg},
#{single_line := true, depth := Depth} = FormatOpts) ->
P = p(FormatOpts),
Format = lists:append(["Undefined handle_info in ", P,
". Unhandled message: ", P, "."]),
Format = lists:append(["Undefined handle_info in ", P, ". Unhandled message: ", P, "."]),
Args =
case Depth of
unlimited ->
@ -911,8 +859,7 @@ format_log_multi(#{label := {gen_event, terminate},
unlimited ->
[Handler, SName, LastIn, State, Reason1];
_ ->
[Handler, Depth, SName, Depth, LastIn, Depth, State, Depth,
Reason1, Depth]
[Handler, Depth, SName, Depth, LastIn, Depth, State, Depth, Reason1, Depth]
end,
{Format, Args};
format_log_multi(#{label := {gen_event, no_handle_info},
@ -940,7 +887,7 @@ fix_reason({'EXIT', {undef, [{M, F, A, _L} | _] = MFAs} = Reason}) ->
case erlang:function_exported(M, F, length(A)) of
true ->
Reason;
false ->
_ ->
{'function not exported', MFAs}
end
end;
@ -962,16 +909,6 @@ single(false) -> "".
mod(latin1) -> "";
mod(_) -> "t".
%% stop_handlers(MSL, ServerName) -> []
stop_handlers([Handler | T], SName) ->
Mod = Handler#handler.module,
do_terminate(Mod, Handler, stop, Handler#handler.state,
stop, SName, shutdown),
stop_handlers(T, SName);
stop_handlers([], _) ->
[].
%% Message from the release_handler.
%% The list of modules got to be a set, i.e. no duplicate elements!
get_modules(EpmHers) ->
@ -981,7 +918,7 @@ allMods(Iterator, Acc) ->
case maps:next(Iterator) of
{_K, V, NextIterator} ->
allMods(NextIterator, [element(#epmHer.epmM, V) | Acc]);
none ->
_ ->
lists:usort(Acc)
end.
@ -998,8 +935,8 @@ allStateStatus(Iterator, Opt, PDict, EpmHers) ->
case maps:next(Iterator) of
{_K, #epmHer{epmM = Module, epmS = EpmS} = V, NextIterator} ->
NewEpmS = format_status(Opt, Module, PDict, EpmS),
allStateStatus(NextIterator, [V#epmHer{epmS = NewEpmS} | EpmHers]);
none ->
allStateStatus(NextIterator, Opt, PDict, [V#epmHer{epmS = NewEpmS} | EpmHers]);
_ ->
EpmHers
end.
@ -1011,7 +948,7 @@ format_status(Opt, Mod, PDict, State) ->
{'EXIT', _} -> State;
Else -> Else
end;
false ->
_ ->
State
end.

Carregando…
Cancelar
Salvar