From d35951a966e294d7705c37c6cacc2077df565bfe Mon Sep 17 00:00:00 2001 From: SisMaker <1713699517@qq.com> Date: Fri, 30 Jun 2023 00:46:05 +0800 Subject: [PATCH] =?UTF-8?q?ft:=20=E7=BB=99=E5=90=84=E7=A7=8D=E8=A1=8C?= =?UTF-8?q?=E4=B8=BA=E5=8A=A0=E4=B8=8A=20=E5=AE=88=E6=8A=A4=20=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F=20=E8=AF=A5=E6=A8=A1=E5=BC=8F=E4=B8=8Btry=20=E6=8D=95?= =?UTF-8?q?=E6=8D=89=E5=88=B0=E9=94=99=E8=AF=AF=E5=90=8E=20=E5=B9=B6?= =?UTF-8?q?=E4=B8=8D=E4=BC=9A=E6=9D=80=E6=AD=BB=E8=BF=9B=E7=A8=8B=20?= =?UTF-8?q?=E8=80=8C=E6=98=AF=E6=89=93=E5=8D=B0=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/genGbh.hrl | 23 + rebar.config | 2 +- src/gen_apu.erl | 2119 ++++++++++++++++++++++---------------------- src/gen_emm.erl | 16 +- src/gen_ipc.erl | 13 +- src/gen_mpp.erl | 14 +- src/gen_srv.erl | 14 +- 7 files changed, 1116 insertions(+), 1085 deletions(-) create mode 100644 include/genGbh.hrl diff --git a/include/genGbh.hrl b/include/genGbh.hrl new file mode 100644 index 0000000..bae742a --- /dev/null +++ b/include/genGbh.hrl @@ -0,0 +1,23 @@ +-ifndef(genGbh_H). +-define(genGbh_H, true). + +-record(gbhOpts, { + daemon = false :: boolean() %% 是否是守护进程模式 try catch 捕捉到出错之后 是否关闭进程 还是仅仅打印日志 调用、handleError +}). + +-ifdef(debug_gbh). +%% debug 调试相关宏定义 +-define(NOT_DEBUG, []). +-define(SYS_DEBUG(Debug, Name, Msg), + case Debug of + ?NOT_DEBUG -> + ok; + _ -> + sys:handle_debug(Debug, fun print_event/3, Name, Msg) + end). +-else. +-define(SYS_DEBUG(Debug, Name, Msg), ok). +-endif. + + +-endif. diff --git a/rebar.config b/rebar.config index a598a3a..8016171 100644 --- a/rebar.config +++ b/rebar.config @@ -1 +1 @@ -{erl_opts, [no_debug_info, deterministic]}. \ No newline at end of file +{erl_opts, [no_debug_info, {i, "include"}, deterministic]}. \ No newline at end of file diff --git a/src/gen_apu.erl b/src/gen_apu.erl index a8b33b8..23d9a78 100644 --- a/src/gen_apu.erl +++ b/src/gen_apu.erl @@ -4,92 +4,84 @@ -compile({inline_size, 128}). -include_lib("kernel/include/logger.hrl"). +-include("genGbh.hrl"). -import(gen_call, [gcall/3, gcall/4, greply/2, try_greply/2]). -export([ - %% API for gen_apu - start/3, start/4, start_link/3, start_link/4 - , start_monitor/3, start_monitor/4 - , stop/1, stop/3 - , call/2, call/3 - , clfn/4, clfn/5, clfs/4, clfs/5, csfn/4, csfs/4 - , send_request/2, wait_response/2, receive_response/2, check_response/2 - , cast/2, send/2, reply/1, reply/2 - , abcast/2, abcast/3 - , multi_call/2, multi_call/3, multi_call/4 - , enter_loop/3, enter_loop/4, enter_loop/5 - - %% gen callbacks - , init_it/6 - - %% sys callbacks - , system_continue/3 - , system_terminate/4 - , system_code_change/4 - , system_get_state/1 - , system_replace_state/2 - , format_status/2 - - %% Internal callbacks - , wakeupFromHib/8 - - %% logger callback - , format_log/1, format_log/2 + %% API for gen_apu + start/3, start/4, start_link/3, start_link/4 + , start_monitor/3, start_monitor/4 + , stop/1, stop/3 + , call/2, call/3 + , clfn/4, clfn/5, clfs/4, clfs/5, csfn/4, csfs/4 + , send_request/2, wait_response/2, receive_response/2, check_response/2 + , cast/2, send/2, reply/1, reply/2 + , abcast/2, abcast/3 + , multi_call/2, multi_call/3, multi_call/4 + , enter_loop/3, enter_loop/4, enter_loop/5 + + %% gen callbacks + , init_it/6 + + %% sys callbacks + , system_continue/3 + , system_terminate/4 + , system_code_change/4 + , system_get_state/1 + , system_replace_state/2 + , format_status/2 + + %% Internal callbacks + , wakeupFromHib/9 + + %% logger callback + , format_log/1, format_log/2, print_event/3 ]). -define(STACKTRACE(), element(2, erlang:process_info(self(), current_stacktrace))). -%% debug 调试相关宏定义 --define(NOT_DEBUG, []). --define(SYS_DEBUG(Debug, Name, Msg), - case Debug of - ?NOT_DEBUG -> - Debug; - _ -> - sys:handle_debug(Debug, fun print_event/3, Name, Msg) - end). - -type serverName() :: - {'local', atom()} | - {'global', GlobalName :: term()} | - {'via', RegMod :: module(), Name :: term()}. +{'local', atom()} | +{'global', GlobalName :: term()} | +{'via', RegMod :: module(), Name :: term()}. -type serverRef() :: - pid() - | (LocalName :: atom()) - | {Name :: atom(), Node :: atom()} - | {'global', GlobalName :: term()} - | {'via', RegMod :: module(), ViaName :: term()}. +pid() +| (LocalName :: atom()) +| {Name :: atom(), Node :: atom()} +| {'global', GlobalName :: term()} +| {'via', RegMod :: module(), ViaName :: term()}. -type startOpt() :: - {'timeout', Time :: timeout()} | - {'spawn_opt', [proc_lib:spawn_option()]} | - enterLoopOpt(). +daemon | +{'timeout', Time :: timeout()} | +{'spawn_opt', [proc_lib:spawn_option()]} | +enterLoopOpt(). -type enterLoopOpt() :: - {'debug', Debugs :: [sys:debug_option()]} | - {'hibernate_after', HibernateAfterTimeout :: timeout()}. +{'debug', Debugs :: [sys:debug_option()]} | +{'hibernate_after', HibernateAfterTimeout :: timeout()}. -type startRet() :: - 'ignore' | - {'ok', pid()} | - {'ok', {pid(), reference()}} | - {'error', term()}. +'ignore' | +{'ok', pid()} | +{'ok', {pid(), reference()}} | +{'error', term()}. -type action() :: - timeout() | - hibernate | - {'doAfter', Args :: term()} | - {'nTimeout', Name :: term(), Time :: timeouts(), TimeoutMsg :: term()} | - {'nTimeout', Name :: term(), Time :: timeouts(), TimeoutMsg :: term(), Options :: ([timeoutOption()])} | - {'uTimeout', Name :: term(), TimeoutMsg :: term()} | - {'cTimeout', Name :: term()}. +timeout() | +hibernate | +{'doAfter', Args :: term()} | +{'nTimeout', Name :: term(), Time :: timeouts(), TimeoutMsg :: term()} | +{'nTimeout', Name :: term(), Time :: timeouts(), TimeoutMsg :: term(), Options :: ([timeoutOption()])} | +{'uTimeout', Name :: term(), TimeoutMsg :: term()} | +{'cTimeout', Name :: term()}. -type actions() :: - action() | - [action(), ...]. +action() | +[action(), ...]. -type timeouts() :: Time :: timeout() | integer(). -type timeoutOption() :: {abs, Abs :: boolean()}. @@ -103,147 +95,154 @@ {'reply', From :: from(), Reply :: term()}. -callback init(Args :: term()) -> - {ok, State :: term()} | - {ok, State :: term(), Actions :: actions()} | - {stop, Reason :: term()} | - ignore. + {ok, State :: term()} | + {ok, State :: term(), Actions :: actions()} | + {stop, Reason :: term()} | + ignore. %% call 消息的返回 -export_type([handleCallRet/0]). -type handleCallRet() :: - kpS | - {reply, Reply :: term()} | - {reply, Reply :: term(), NewState :: term()} | - {reply, Reply :: term(), NewState :: term(), Actions :: actions()} | - {noreply, NewState :: term()} | - {noreply, NewState :: term(), Actions :: actions()} | - {mayReply, Reply :: term()} | - {mayReply, Reply :: term(), NewState :: term()} | - {mayReply, Reply :: term(), NewState :: term(), Actions :: actions()} | - {stop, Reason :: term(), NewState :: term()} | - {stopReply, Reason :: term(), Reply :: term(), NewState :: term()}. +kpS | +{reply, Reply :: term()} | +{reply, Reply :: term(), NewState :: term()} | +{reply, Reply :: term(), NewState :: term(), Actions :: actions()} | +{noreply, NewState :: term()} | +{noreply, NewState :: term(), Actions :: actions()} | +{mayReply, Reply :: term()} | +{mayReply, Reply :: term(), NewState :: term()} | +{mayReply, Reply :: term(), NewState :: term(), Actions :: actions()} | +{stop, Reason :: term(), NewState :: term()} | +{stopReply, Reason :: term(), Reply :: term(), NewState :: term()}. %% cast 消息的返回 -export_type([handleCastRet/0]). -type handleCastRet() :: - kpS | - {noreply, NewState :: term()} | - {noreply, NewState :: term(), Actions :: actions()} | - {stop, Reason :: term(), NewState :: term()}. +kpS | +{noreply, NewState :: term()} | +{noreply, NewState :: term(), Actions :: actions()} | +{stop, Reason :: term(), NewState :: term()}. -callback handleInfo(Info :: timeout | term(), State :: term()) -> - kpS | - {noreply, NewState :: term()} | - {noreply, NewState :: term(), Actions :: actions()} | - {stop, Reason :: term(), NewState :: term()}. + kpS | + {noreply, NewState :: term()} | + {noreply, NewState :: term(), Actions :: actions()} | + {stop, Reason :: term(), NewState :: term()}. + +-callback handleError(Error :: term(), State :: term()) -> + kpS | + {noreply, NewState :: term()} | + {noreply, NewState :: term(), Actions :: actions()} | + {stop, Reason :: term(), NewState :: term()}. -callback handleAfter(Info :: term(), State :: term()) -> - kpS | - {noreply, NewState :: term()} | - {noreply, NewState :: term(), Actions :: actions()} | - {stop, Reason :: term(), NewState :: term()}. + kpS | + {noreply, NewState :: term()} | + {noreply, NewState :: term(), Actions :: actions()} | + {stop, Reason :: term(), NewState :: term()}. -callback terminate(Reason :: (normal | shutdown | {shutdown, term()} |term()), State :: term()) -> - term(). + term(). -callback code_change(OldVsn :: (term() | {down, term()}), State :: term(), Extra :: term()) -> - {ok, NewState :: term()} | {error, Reason :: term()}. + {ok, NewState :: term()} | {error, Reason :: term()}. -callback formatStatus(Opt, StatusData) -> Status when - Opt :: 'normal' | 'terminate', - StatusData :: [PDict | State], - PDict :: [{Key :: term(), Value :: term()}], - State :: term(), - Status :: term(). + Opt :: 'normal' | 'terminate', + StatusData :: [PDict | State], + PDict :: [{Key :: term(), Value :: term()}], + State :: term(), + Status :: term(). -optional_callbacks([ - handleAfter/2 - , handleInfo/2 - , terminate/2 - , code_change/3 - , formatStatus/2 +handleAfter/2 +, handleInfo/2 +, terminate/2 +, code_change/3 +, formatStatus/2 ]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% start stop API start %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -spec start(Module :: module(), Args :: term(), Opts :: [startOpt()]) -> startRet(). start(Module, Args, Options) -> - gen:start(?MODULE, nolink, Module, Args, Options). + gen:start(?MODULE, nolink, Module, Args, Options). -spec start(ServerName :: serverName(), Module :: module(), Args :: term(), Opts :: [startOpt()]) -> startRet(). start(ServerName, Module, Args, Options) -> - gen:start(?MODULE, nolink, ServerName, Module, Args, Options). + gen:start(?MODULE, nolink, ServerName, Module, Args, Options). -spec start_link(Module :: module(), Args :: term(), Opts :: [startOpt()]) -> startRet(). start_link(Module, Args, Options) -> - gen:start(?MODULE, link, Module, Args, Options). + gen:start(?MODULE, link, Module, Args, Options). -spec start_link(ServerName :: serverName(), Module :: module(), Args :: term(), Opts :: [startOpt()]) -> startRet(). start_link(ServerName, Module, Args, Options) -> - gen:start(?MODULE, link, ServerName, Module, Args, Options). + gen:start(?MODULE, link, ServerName, Module, Args, Options). -spec start_monitor(Module :: module(), Args :: term(), Opts :: [startOpt()]) -> startRet(). start_monitor(Module, Args, Options) -> - gen:start(?MODULE, monitor, Module, Args, Options). + gen:start(?MODULE, monitor, Module, Args, Options). -spec start_monitor(ServerName :: serverName(), Module :: module(), Args :: term(), Opts :: [startOpt()]) -> startRet(). start_monitor(ServerName, Module, Args, Options) -> - gen:start(?MODULE, monitor, ServerName, Module, Args, Options). + gen:start(?MODULE, monitor, ServerName, Module, Args, Options). %%停止通用服务器并等待其终止。如果服务器位于另一个节点上,则将监视该节点。 -spec stop(ServerRef :: serverRef()) -> ok. stop(ServerRef) -> - gen:stop(ServerRef). + gen:stop(ServerRef). -spec stop(ServerRef :: serverRef(), Reason :: term(), Timeout :: timeout()) -> ok. stop(ServerRef, Reason, Timeout) -> - gen:stop(ServerRef, Reason, Timeout). + gen:stop(ServerRef, Reason, Timeout). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% start stop API end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% gen callbacks start %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% doModuleInit(Module, Args) -> - try - Module:init(Args) - catch - throw:Ret -> Ret; - Class:Reason:Strace -> {'EXIT', Class, Reason, Strace} - end. + try + Module:init(Args) + catch + throw:Ret -> Ret; + Class:Reason:Strace -> {'EXIT', Class, Reason, Strace} + end. init_it(Starter, self, ServerRef, Module, Args, Options) -> - init_it(Starter, self(), ServerRef, Module, Args, Options); + init_it(Starter, self(), ServerRef, Module, Args, Options); init_it(Starter, Parent, ServerRef, Module, Args, Options) -> - Name = gen:name(ServerRef), - Debug = gen:debug_options(Name, Options), - HibernateAfterTimeout = gen:hibernate_after(Options), - - case doModuleInit(Module, Args) of - {ok, State} -> - proc_lib:init_ack(Starter, {ok, self()}), - receiveIng(Parent, Name, Module, HibernateAfterTimeout, Debug, #{}, State, false); - {ok, State, Actions} -> - proc_lib:init_ack(Starter, {ok, self()}), - loopEntry(Parent, Name, Module, HibernateAfterTimeout, Debug, #{}, State, listify(Actions)); - {stop, Reason} -> - % 为了保持一致性,我们必须确保在 - % %%父进程收到有关失败的通知之前,必须先注销%%注册名称(如果有)。 - % %%(否则,如果父进程立即%%再次尝试启动该进程,则其父进程可能会收到%already_started错误)。 - gen:unregister_name(ServerRef), - proc_lib:init_ack(Starter, {error, Reason}), - exit(Reason); - ignore -> - gen:unregister_name(ServerRef), - proc_lib:init_ack(Starter, ignore), - exit(normal); - {'EXIT', Class, Reason, Stacktrace} -> - gen:unregister_name(ServerRef), - proc_lib:init_ack(Starter, {error, terminate_reason(Class, Reason, Stacktrace)}), - erlang:raise(Class, Reason, Stacktrace); - _Ret -> - Error = {bad_return_value, _Ret}, - proc_lib:init_ack(Starter, {error, Error}), - exit(Error) - end. + Name = gen:name(ServerRef), + Debug = gen:debug_options(Name, Options), + GbhOpts = #gbhOpts{daemon = lists:member(daemon, Options)}, + HibernateAfterTimeout = gen:hibernate_after(Options), + + case doModuleInit(Module, Args) of + {ok, State} -> + proc_lib:init_ack(Starter, {ok, self()}), + receiveIng(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, #{}, State, false); + {ok, State, Actions} -> + proc_lib:init_ack(Starter, {ok, self()}), + loopEntry(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, #{}, State, listify(Actions)); + {stop, Reason} -> + % 为了保持一致性,我们必须确保在 + % %%父进程收到有关失败的通知之前,必须先注销%%注册名称(如果有)。 + % %%(否则,如果父进程立即%%再次尝试启动该进程,则其父进程可能会收到%already_started错误)。 + gen:unregister_name(ServerRef), + proc_lib:init_ack(Starter, {error, Reason}), + exit(Reason); + ignore -> + gen:unregister_name(ServerRef), + proc_lib:init_ack(Starter, ignore), + exit(normal); + {'EXIT', Class, Reason, Stacktrace} -> + gen:unregister_name(ServerRef), + proc_lib:init_ack(Starter, {error, terminate_reason(Class, Reason, Stacktrace)}), + erlang:raise(Class, Reason, Stacktrace); + _Ret -> + Error = {bad_return_value, _Ret}, + proc_lib:init_ack(Starter, {error, Error}), + exit(Error) + end. %%----------------------------------------------------------------- @@ -259,77 +258,78 @@ init_it(Starter, Parent, ServerRef, Module, Args, Options) -> %%----------------------------------------------------------------- -spec enter_loop(Module :: module(), State :: term(), Opts :: [enterLoopOpt()]) -> no_return(). enter_loop(Module, State, Opts) -> - enter_loop(Module, State, Opts, self(), infinity). + enter_loop(Module, State, Opts, self(), infinity). -spec enter_loop(Module :: module(), State :: term(), Opts :: [enterLoopOpt()], serverName() | pid()) -> no_return(). enter_loop(Module, State, Opts, ServerName) -> - enter_loop(Module, State, Opts, ServerName, infinity). + enter_loop(Module, State, Opts, ServerName, infinity). -spec enter_loop(Module :: module(), State :: term(), Opts :: [enterLoopOpt()], Server :: serverName() | pid(), Actions :: actions()) -> no_return(). enter_loop(Module, State, Opts, ServerName, Actions) -> - Name = gen:get_proc_name(ServerName), - Parent = gen:get_parent(), - Debug = gen:debug_options(Name, Opts), - HibernateAfterTimeout = gen:hibernate_after(Opts), - loopEntry(Parent, Name, Module, HibernateAfterTimeout, Debug, #{}, State, listify(Actions)). + Name = gen:get_proc_name(ServerName), + Parent = gen:get_parent(), + Debug = gen:debug_options(Name, Opts), + GbhOpts = #gbhOpts{daemon = lists:member(daemon, Opts)}, + HibernateAfterTimeout = gen:hibernate_after(Opts), + loopEntry(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, #{}, State, listify(Actions)). %%% Internal callbacks -wakeupFromHib(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, IsHib) -> - %% 这是一条新消息,唤醒了我们,因此我们必须立即收到它 - receiveIng(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, IsHib). - -loopEntry(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, Actions) -> - case doParseAL(Actions, Name, Debug, false, false, Timers) of - {error, ErrorContent} -> - terminate(error, ErrorContent, ?STACKTRACE(), Name, Module, Debug, Timers, CurState, []); - {NewDebug, IsHib, DoAfter, NewTimers} -> - case DoAfter of - {doAfter, Args} -> - doAfterCall(Parent, Name, Module, HibernateAfterTimeout, NewDebug, NewTimers, CurState, listHib(IsHib), Args); - _ -> - case IsHib of - true -> - proc_lib:hibernate(?MODULE, wakeupFromHib, [Parent, Name, Module, HibernateAfterTimeout, NewDebug, NewTimers, CurState, IsHib]); - _ -> - receiveIng(Parent, Name, Module, HibernateAfterTimeout, NewDebug, NewTimers, CurState, false) - end - end - end. +wakeupFromHib(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, IsHib) -> + %% 这是一条新消息,唤醒了我们,因此我们必须立即收到它 + receiveIng(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, IsHib). + +loopEntry(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Actions) -> + case doParseAL(Actions, Name, Debug, false, false, Timers) of + {error, ErrorContent} -> + innerError(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Actions, error, ErrorContent, []); + {Debug, IsHib, DoAfter, NewTimers} -> + case DoAfter of + {doAfter, Args} -> + doAfterCall(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, NewTimers, CurState, listHib(IsHib), Args); + _ -> + case IsHib of + true -> + proc_lib:hibernate(?MODULE, wakeupFromHib, [Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, NewTimers, CurState, IsHib]); + _ -> + receiveIng(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, NewTimers, CurState, false) + end + end + end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% sys callbacks start %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%----------------------------------------------------------------- %% Callback functions for system messages handling. %%----------------------------------------------------------------- -system_continue(Parent, Debug, {Name, Module, HibernateAfterTimeout, Timers, CurState, IsHib}) -> - case IsHib of - true -> - proc_lib:hibernate(?MODULE, wakeupFromHib, [Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, IsHib]); - _ -> - receiveIng(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, IsHib) - end. +system_continue(Parent, Debug, {Name, Module, GbhOpts, HibernateAfterTimeout, Timers, CurState, IsHib}) -> + case IsHib of + true -> + proc_lib:hibernate(?MODULE, wakeupFromHib, [Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, IsHib]); + _ -> + receiveIng(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, IsHib) + end. -spec system_terminate(_, _, _, [_]) -> no_return(). -system_terminate(Reason, _Parent, Debug, {Name, Module, _HibernateAfterTimeout, Timers, CurState, _IsHib}) -> - terminate(exit, Reason, ?STACKTRACE(), Name, Module, Debug, Timers, CurState, []). - -system_code_change({Name, Module, HibernateAfterTimeout, Timers, CurState, IsHib}, _Module, OldVsn, Extra) -> - case - try Module:code_change(OldVsn, CurState, Extra) - catch - throw:Result -> Result; - _C:_R:_S -> {_C, _R, _S} - end - of - {ok, NewState} -> {ok, {Name, Module, HibernateAfterTimeout, Timers, NewState, IsHib}}; - Error -> Error - end. - -system_get_state({_Name, _Module, _HibernateAfterTimeout, _Timers, CurState, _IsHib}) -> - {ok, CurState}. - -system_replace_state(StateFun, {Name, Module, HibernateAfterTimeout, Timers, CurState, IsHib}) -> - NewState = StateFun(CurState), - {ok, NewState, {Name, Module, HibernateAfterTimeout, Timers, NewState, IsHib}}. +system_terminate(Reason, _Parent, Debug, {Name, Module, _GbhOpts, _HibernateAfterTimeout, Timers, CurState, _IsHib}) -> + terminate(exit, Reason, ?STACKTRACE(), Name, Module, Debug, Timers, CurState, []). + +system_code_change({Name, Module, GbhOpts, HibernateAfterTimeout, Timers, CurState, IsHib}, _Module, OldVsn, Extra) -> + case + try Module:code_change(OldVsn, CurState, Extra) + catch + throw:Result -> Result; + _C:_R:_S -> {_C, _R, _S} + end + of + {ok, NewState} -> {ok, {Name, Module, GbhOpts, HibernateAfterTimeout, Timers, NewState, IsHib}}; + Error -> Error + end. + +system_get_state({_Name, _Module, _GbhOpts, _HibernateAfterTimeout, _Timers, CurState, _IsHib}) -> + {ok, CurState}. + +system_replace_state(StateFun, {Name, Module, GbhOpts, HibernateAfterTimeout, Timers, CurState, IsHib}) -> + NewState = StateFun(CurState), + {ok, NewState, {Name, Module, GbhOpts, HibernateAfterTimeout, Timers, NewState, IsHib}}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% sys callbacks end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% API helpers start %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -341,91 +341,91 @@ system_replace_state(StateFun, {Name, Module, HibernateAfterTimeout, Timers, Cur %% is handled here (? Shall we do that here (or rely on timeouts) ?). -spec call(ServerRef :: serverRef(), Request :: term()) -> Reply :: term(). call(ServerRef, Request) -> - try gcall(ServerRef, '$gen_call', Request) of - {ok, Reply} -> - Reply - catch Class:Reason -> - erlang:raise(Class, {Reason, {?MODULE, call, [ServerRef, Request]}}, ?STACKTRACE()) - end. + try gcall(ServerRef, '$gen_call', Request) of + {ok, Reply} -> + Reply + catch Class:Reason -> + erlang:raise(Class, {Reason, {?MODULE, call, [ServerRef, Request]}}, ?STACKTRACE()) + end. -spec call(ServerRef :: serverRef(), Request :: term(), Timeout :: timeout()) -> Reply :: term(). call(ServerRef, Request, Timeout) -> - try gcall(ServerRef, '$gen_call', Request, Timeout) of - {ok, Reply} -> - Reply - catch Class:Reason -> - erlang:raise(Class, {Reason, {?MODULE, call, [ServerRef, Request]}}, ?STACKTRACE()) - end. + try gcall(ServerRef, '$gen_call', Request, Timeout) of + {ok, Reply} -> + Reply + catch Class:Reason -> + erlang:raise(Class, {Reason, {?MODULE, call, [ServerRef, Request]}}, ?STACKTRACE()) + end. -spec clfn(ServerRef :: serverRef(), M :: module(), F :: atom(), A :: list()) -> ok. clfn(ServerRef, M, F, A) -> - try gcall(ServerRef, '$gen_clfn', {M, F, A}) of - {ok, Reply} -> - Reply - catch Class:Reason -> - erlang:raise(Class, {Reason, {?MODULE, clfn, [ServerRef, {M, F, A}]}}, ?STACKTRACE()) - end. + try gcall(ServerRef, '$gen_clfn', {M, F, A}) of + {ok, Reply} -> + Reply + catch Class:Reason -> + erlang:raise(Class, {Reason, {?MODULE, clfn, [ServerRef, {M, F, A}]}}, ?STACKTRACE()) + end. -spec clfn(ServerRef :: serverRef(), M :: module(), F :: atom(), A :: list(), Timeout :: timeout()) -> ok. clfn(ServerRef, M, F, A, Timeout) -> - try gcall(ServerRef, '$gen_clfn', {M, F, A}, Timeout) of - {ok, Reply} -> - Reply - catch Class:Reason -> - erlang:raise(Class, {Reason, {?MODULE, clfn, [ServerRef, {M, F, A}]}}, ?STACKTRACE()) - end. + try gcall(ServerRef, '$gen_clfn', {M, F, A}, Timeout) of + {ok, Reply} -> + Reply + catch Class:Reason -> + erlang:raise(Class, {Reason, {?MODULE, clfn, [ServerRef, {M, F, A}]}}, ?STACKTRACE()) + end. -spec clfs(ServerRef :: serverRef(), M :: module(), F :: atom(), A :: list()) -> ok. clfs(ServerRef, M, F, A) -> - try gcall(ServerRef, '$gen_clfs', {M, F, A}) of - {ok, Reply} -> - Reply - catch Class:Reason -> - erlang:raise(Class, {Reason, {?MODULE, clfs, [ServerRef, {M, F, A}]}}, ?STACKTRACE()) - end. + try gcall(ServerRef, '$gen_clfs', {M, F, A}) of + {ok, Reply} -> + Reply + catch Class:Reason -> + erlang:raise(Class, {Reason, {?MODULE, clfs, [ServerRef, {M, F, A}]}}, ?STACKTRACE()) + end. -spec clfs(ServerRef :: serverRef(), M :: module(), F :: atom(), A :: list(), Timeout :: timeout()) -> ok. clfs(ServerRef, M, F, A, Timeout) -> - try gcall(ServerRef, '$gen_clfs', {M, F, A}, Timeout) of - {ok, Reply} -> - Reply - catch Class:Reason -> - erlang:raise(Class, {Reason, {?MODULE, clfs, [ServerRef, {M, F, A}]}}, ?STACKTRACE()) - end. + try gcall(ServerRef, '$gen_clfs', {M, F, A}, Timeout) of + {ok, Reply} -> + Reply + catch Class:Reason -> + erlang:raise(Class, {Reason, {?MODULE, clfs, [ServerRef, {M, F, A}]}}, ?STACKTRACE()) + end. -spec csfn(ServerRef :: serverRef(), M :: module(), F :: atom(), A :: list()) -> ok. csfn({global, Name}, M, F, A) -> - try global:send(Name, {'$gen_csfn', {M, F, A}}), - ok - catch _:_ -> ok - end; + try global:send(Name, {'$gen_csfn', {M, F, A}}), + ok + catch _:_ -> ok + end; csfn({via, RegMod, Name}, M, F, A) -> - try RegMod:send(Name, {'$gen_csfn', {M, F, A}}), - ok - catch _:_ -> ok - end; + try RegMod:send(Name, {'$gen_csfn', {M, F, A}}), + ok + catch _:_ -> ok + end; csfn(Dest, M, F, A) -> - try erlang:send(Dest, {'$gen_csfn', {M, F, A}}), - ok - catch _:_ -> ok - end. + try erlang:send(Dest, {'$gen_csfn', {M, F, A}}), + ok + catch _:_ -> ok + end. -spec csfs(ServerRef :: serverRef(), M :: module(), F :: atom(), A :: list()) -> ok. csfs({global, Name}, M, F, A) -> - try global:send(Name, {'$gen_csfs', {M, F, A}}), - ok - catch _:_ -> ok - end; + try global:send(Name, {'$gen_csfs', {M, F, A}}), + ok + catch _:_ -> ok + end; csfs({via, RegMod, Name}, M, F, A) -> - try RegMod:send(Name, {'$gen_csfs', {M, F, A}}), - ok - catch _:_ -> ok - end; + try RegMod:send(Name, {'$gen_csfs', {M, F, A}}), + ok + catch _:_ -> ok + end; csfs(Dest, M, F, A) -> - try erlang:send(Dest, {'$gen_csfs', {M, F, A}}), - ok - catch _:_ -> ok - end. + try erlang:send(Dest, {'$gen_csfs', {M, F, A}}), + ok + catch _:_ -> ok + end. %%% ----------------------------------------------------------------- %%% Make a call to servers at several nodes. @@ -439,126 +439,126 @@ csfs(Dest, M, F, A) -> %%% ----------------------------------------------------------------- multi_call(Name, Request) when is_atom(Name) -> - do_multi_call([node() | nodes()], Name, Request, infinity). + do_multi_call([node() | nodes()], Name, Request, infinity). multi_call(Nodes, Name, Request) when is_list(Nodes), is_atom(Name) -> - do_multi_call(Nodes, Name, Request, infinity). + do_multi_call(Nodes, Name, Request, infinity). multi_call(Nodes, Name, Request, infinity) -> - do_multi_call(Nodes, Name, Request, infinity); + do_multi_call(Nodes, Name, Request, infinity); multi_call(Nodes, Name, Request, Timeout) when is_list(Nodes), is_atom(Name), is_integer(Timeout), Timeout >= 0 -> - do_multi_call(Nodes, Name, Request, Timeout). + do_multi_call(Nodes, Name, Request, Timeout). do_multi_call([Node], Name, Req, infinity) when Node =:= node() -> - % Special case when multi_call is used with local node only. - % In that case we can leverage the benefit of recv_mark optimisation - % existing in simple gcall. - try gcall(Name, '$gen_call', Req, infinity) of - {ok, Res} -> {[{Node, Res}], []} - catch exit:_ -> - {[], [Node]} - end; + % Special case when multi_call is used with local node only. + % In that case we can leverage the benefit of recv_mark optimisation + % existing in simple gcall. + try gcall(Name, '$gen_call', Req, infinity) of + {ok, Res} -> {[{Node, Res}], []} + catch exit:_ -> + {[], [Node]} + end; do_multi_call(Nodes, Name, Request, infinity) -> - Tag = make_ref(), - Monitors = send_nodes(Nodes, Name, Tag, Request), - rec_nodes(Tag, Monitors, Name, undefined); + Tag = make_ref(), + Monitors = send_nodes(Nodes, Name, Tag, Request), + rec_nodes(Tag, Monitors, Name, undefined); do_multi_call(Nodes, Name, Request, Timeout) -> - Tag = make_ref(), - Caller = self(), - Receiver = spawn( - fun() -> - process_flag(trap_exit, true), - Mref = erlang:monitor(process, Caller), - receive - {Caller, Tag} -> - Monitors = send_nodes(Nodes, Name, Tag, Request), - TimerId = erlang:start_timer(Timeout, self(), ok), - Result = rec_nodes(Tag, Monitors, Name, TimerId), - exit({self(), Tag, Result}); - {'DOWN', Mref, _, _, _} -> - exit(normal) - end - end - ), - Mref = erlang:monitor(process, Receiver), - Receiver ! {self(), Tag}, - receive - {'DOWN', Mref, _, _, {Receiver, Tag, Result}} -> - Result; - {'DOWN', Mref, _, _, Reason} -> - exit(Reason) - end. + Tag = make_ref(), + Caller = self(), + Receiver = spawn( + fun() -> + process_flag(trap_exit, true), + Mref = erlang:monitor(process, Caller), + receive + {Caller, Tag} -> + Monitors = send_nodes(Nodes, Name, Tag, Request), + TimerId = erlang:start_timer(Timeout, self(), ok), + Result = rec_nodes(Tag, Monitors, Name, TimerId), + exit({self(), Tag, Result}); + {'DOWN', Mref, _, _, _} -> + exit(normal) + end + end + ), + Mref = erlang:monitor(process, Receiver), + Receiver ! {self(), Tag}, + receive + {'DOWN', Mref, _, _, {Receiver, Tag, Result}} -> + Result; + {'DOWN', Mref, _, _, Reason} -> + exit(Reason) + end. -spec cast(ServerRef :: serverRef(), Msg :: term()) -> ok. cast({global, Name}, Msg) -> - try global:send(Name, {'$gen_cast', Msg}), - ok - catch _:_ -> ok - end; + try global:send(Name, {'$gen_cast', Msg}), + ok + catch _:_ -> ok + end; cast({via, RegMod, Name}, Msg) -> - try RegMod:send(Name, {'$gen_cast', Msg}), - ok - catch _:_ -> ok - end; + try RegMod:send(Name, {'$gen_cast', Msg}), + ok + catch _:_ -> ok + end; cast(Dest, Msg) -> - try erlang:send(Dest, {'$gen_cast', Msg}), - ok - catch _:_ -> ok - end. + try erlang:send(Dest, {'$gen_cast', Msg}), + ok + catch _:_ -> ok + end. -spec send(ServerRef :: serverRef(), Msg :: term()) -> ok. send({global, Name}, Msg) -> - try global:send(Name, Msg), - ok - catch _:_ -> ok - end; + try global:send(Name, Msg), + ok + catch _:_ -> ok + end; send({via, RegMod, Name}, Msg) -> - try RegMod:send(Name, Msg), - ok - catch _:_ -> ok - end; + try RegMod:send(Name, Msg), + ok + catch _:_ -> ok + end; send(Dest, Msg) -> - try erlang:send(Dest, Msg), - ok - catch _:_ -> ok - end. + try erlang:send(Dest, Msg), + ok + catch _:_ -> ok + end. %% 异步广播,不返回任何内容,只是发送“ n”祈祷 abcast(Name, Msg) when is_atom(Name) -> - doAbcast([node() | nodes()], Name, Msg). + doAbcast([node() | nodes()], Name, Msg). abcast(Nodes, Name, Msg) when is_list(Nodes), is_atom(Name) -> - doAbcast(Nodes, Name, Msg). + doAbcast(Nodes, Name, Msg). doAbcast(Nodes, Name, Msg) -> - [ - begin - try erlang:send({Name, Node}, {'$gen_cast', Msg}), - ok - catch - _:_ -> ok - end - end || Node <- Nodes - ], - ok. + [ + begin + try erlang:send({Name, Node}, {'$gen_cast', Msg}), + ok + catch + _:_ -> ok + end + end || Node <- Nodes + ], + ok. %% Reply from a status machine callback to whom awaits in call/2 -spec reply([replyAction(), ...] | replyAction()) -> ok. reply({reply, {To, Tag}, Reply}) -> - try To ! {Tag, Reply}, - ok - catch _:_ -> - ok - end; + try To ! {Tag, Reply}, + ok + catch _:_ -> + ok + end; reply(Replies) when is_list(Replies) -> - [greply(From, Reply) || {reply, From, Reply} <- Replies], - ok. + [greply(From, Reply) || {reply, From, Reply} <- Replies], + ok. -compile({inline, [reply/2]}). -spec reply(From :: from(), Reply :: term()) -> ok. reply(From, Reply) -> - greply(From, Reply). + greply(From, Reply). %% ----------------------------------------------------------------- %% Send a request to a generic server and return a Key which should be @@ -567,33 +567,33 @@ reply(From, Reply) -> -spec send_request(Name :: serverRef(), Request :: term()) -> requestId(). send_request(Name, Request) -> - gen:send_request(Name, '$gen_call', Request). + gen:send_request(Name, '$gen_call', Request). -spec wait_response(RequestId :: requestId(), timeout()) -> - {reply, Reply :: term()} | 'timeout' | {error, {Reason :: term(), serverRef()}}. + {reply, Reply :: term()} | 'timeout' | {error, {Reason :: term(), serverRef()}}. wait_response(RequestId, Timeout) -> - gen:wait_response(RequestId, Timeout). + gen:wait_response(RequestId, Timeout). -spec receive_response(RequestId :: requestId(), timeout()) -> {reply, Reply :: term()} | 'timeout' | {error, {Reason :: term(), serverRef()}}. receive_response(RequestId, Timeout) -> - gen:receive_response(RequestId, Timeout). + gen:receive_response(RequestId, Timeout). -spec check_response(Msg :: term(), RequestId :: requestId()) -> - {reply, Reply :: term()} | 'no_reply' | {error, {Reason :: term(), serverRef()}}. + {reply, Reply :: term()} | 'no_reply' | {error, {Reason :: term(), serverRef()}}. check_response(Msg, RequestId) -> - gen:check_response(Msg, RequestId). + gen:check_response(Msg, RequestId). send_nodes(Nodes, Name, Tag, Request) -> - [ - begin - Monitor = start_monitor(Node, Name), - try {Name, Node} ! {'$gen_call', {self(), {Tag, Node}}, Request}, - ok - catch _:_ -> ok - end, - Monitor - end || Node <- Nodes, is_atom(Node) - ]. + [ + begin + Monitor = start_monitor(Node, Name), + try {Name, Node} ! {'$gen_call', {self(), {Tag, Node}}, Request}, + ok + catch _:_ -> ok + end, + Monitor + end || Node <- Nodes, is_atom(Node) + ]. %% Against old nodes: %% If no reply has been delivered within 2 secs. (per node) check that @@ -603,431 +603,452 @@ send_nodes(Nodes, Name, Tag, Request) -> %% Wait for reply, server 'DOWN', or timeout from TimerId. rec_nodes(Tag, Nodes, Name, TimerId) -> - rec_nodes(Tag, Nodes, Name, [], [], 2000, TimerId). + rec_nodes(Tag, Nodes, Name, [], [], 2000, TimerId). rec_nodes(Tag, [{N, R} | Tail], Name, Badnodes, Replies, Time, TimerId) -> - receive - {'DOWN', R, _, _, _} -> - rec_nodes(Tag, Tail, Name, [N | Badnodes], Replies, Time, TimerId); - {{Tag, N}, Reply} -> %% Tag is bound !!! - erlang:demonitor(R, [flush]), - rec_nodes(Tag, Tail, Name, Badnodes, - [{N, Reply} | Replies], Time, TimerId); - {timeout, TimerId, _} -> - erlang:demonitor(R, [flush]), - %% Collect all replies that already have arrived - rec_nodes_rest(Tag, Tail, Name, [N | Badnodes], Replies) - end; + receive + {'DOWN', R, _, _, _} -> + rec_nodes(Tag, Tail, Name, [N | Badnodes], Replies, Time, TimerId); + {{Tag, N}, Reply} -> %% Tag is bound !!! + erlang:demonitor(R, [flush]), + rec_nodes(Tag, Tail, Name, Badnodes, + [{N, Reply} | Replies], Time, TimerId); + {timeout, TimerId, _} -> + erlang:demonitor(R, [flush]), + %% Collect all replies that already have arrived + rec_nodes_rest(Tag, Tail, Name, [N | Badnodes], Replies) + end; rec_nodes(Tag, [N | Tail], Name, Badnodes, Replies, Time, TimerId) -> - %% R6 node - receive - {nodedown, N} -> - monitor_node(N, false), - rec_nodes(Tag, Tail, Name, [N | Badnodes], Replies, 2000, TimerId); - {{Tag, N}, Reply} -> %% Tag is bound !!! - receive {nodedown, N} -> ok after 0 -> ok end, - monitor_node(N, false), - rec_nodes(Tag, Tail, Name, Badnodes, - [{N, Reply} | Replies], 2000, TimerId); - {timeout, TimerId, _} -> - receive {nodedown, N} -> ok after 0 -> ok end, - monitor_node(N, false), - %% Collect all replies that already have arrived - rec_nodes_rest(Tag, Tail, Name, [N | Badnodes], Replies) - after Time -> - case erpc:call(N, erlang, whereis, [Name]) of - Pid when is_pid(Pid) -> % It exists try again. - rec_nodes(Tag, [N | Tail], Name, Badnodes, - Replies, infinity, TimerId); - _ -> % badnode - receive {nodedown, N} -> ok after 0 -> ok end, - monitor_node(N, false), - rec_nodes(Tag, Tail, Name, [N | Badnodes], - Replies, 2000, TimerId) - end - end; + %% R6 node + receive + {nodedown, N} -> + monitor_node(N, false), + rec_nodes(Tag, Tail, Name, [N | Badnodes], Replies, 2000, TimerId); + {{Tag, N}, Reply} -> %% Tag is bound !!! + receive {nodedown, N} -> ok after 0 -> ok end, + monitor_node(N, false), + rec_nodes(Tag, Tail, Name, Badnodes, + [{N, Reply} | Replies], 2000, TimerId); + {timeout, TimerId, _} -> + receive {nodedown, N} -> ok after 0 -> ok end, + monitor_node(N, false), + %% Collect all replies that already have arrived + rec_nodes_rest(Tag, Tail, Name, [N | Badnodes], Replies) + after Time -> + case erpc:call(N, erlang, whereis, [Name]) of + Pid when is_pid(Pid) -> % It exists try again. + rec_nodes(Tag, [N | Tail], Name, Badnodes, + Replies, infinity, TimerId); + _ -> % badnode + receive {nodedown, N} -> ok after 0 -> ok end, + monitor_node(N, false), + rec_nodes(Tag, Tail, Name, [N | Badnodes], + Replies, 2000, TimerId) + end + end; rec_nodes(_, [], _, Badnodes, Replies, _, TimerId) -> - case catch erlang:cancel_timer(TimerId) of - false -> % It has already sent it's message - receive - {timeout, TimerId, _} -> ok - after 0 -> - ok - end; - _ -> % Timer was cancelled, or TimerId was 'undefined' - ok - end, - {Replies, Badnodes}. + case catch erlang:cancel_timer(TimerId) of + false -> % It has already sent it's message + receive + {timeout, TimerId, _} -> ok + after 0 -> + ok + end; + _ -> % Timer was cancelled, or TimerId was 'undefined' + ok + end, + {Replies, Badnodes}. %% Collect all replies that already have arrived rec_nodes_rest(Tag, [{N, R} | Tail], Name, Badnodes, Replies) -> - receive - {'DOWN', R, _, _, _} -> - rec_nodes_rest(Tag, Tail, Name, [N | Badnodes], Replies); - {{Tag, N}, Reply} -> %% Tag is bound !!! - erlang:demonitor(R, [flush]), - rec_nodes_rest(Tag, Tail, Name, Badnodes, [{N, Reply} | Replies]) - after 0 -> - erlang:demonitor(R, [flush]), - rec_nodes_rest(Tag, Tail, Name, [N | Badnodes], Replies) - end; + receive + {'DOWN', R, _, _, _} -> + rec_nodes_rest(Tag, Tail, Name, [N | Badnodes], Replies); + {{Tag, N}, Reply} -> %% Tag is bound !!! + erlang:demonitor(R, [flush]), + rec_nodes_rest(Tag, Tail, Name, Badnodes, [{N, Reply} | Replies]) + after 0 -> + erlang:demonitor(R, [flush]), + rec_nodes_rest(Tag, Tail, Name, [N | Badnodes], Replies) + end; rec_nodes_rest(Tag, [N | Tail], Name, Badnodes, Replies) -> - %% R6 node - receive - {nodedown, N} -> - monitor_node(N, false), - rec_nodes_rest(Tag, Tail, Name, [N | Badnodes], Replies); - {{Tag, N}, Reply} -> %% Tag is bound !!! - receive {nodedown, N} -> ok after 0 -> ok end, - monitor_node(N, false), - rec_nodes_rest(Tag, Tail, Name, Badnodes, [{N, Reply} | Replies]) - after 0 -> - receive {nodedown, N} -> ok after 0 -> ok end, - monitor_node(N, false), - rec_nodes_rest(Tag, Tail, Name, [N | Badnodes], Replies) - end; + %% R6 node + receive + {nodedown, N} -> + monitor_node(N, false), + rec_nodes_rest(Tag, Tail, Name, [N | Badnodes], Replies); + {{Tag, N}, Reply} -> %% Tag is bound !!! + receive {nodedown, N} -> ok after 0 -> ok end, + monitor_node(N, false), + rec_nodes_rest(Tag, Tail, Name, Badnodes, [{N, Reply} | Replies]) + after 0 -> + receive {nodedown, N} -> ok after 0 -> ok end, + monitor_node(N, false), + rec_nodes_rest(Tag, Tail, Name, [N | Badnodes], Replies) + end; rec_nodes_rest(_Tag, [], _Name, Badnodes, Replies) -> - {Replies, Badnodes}. + {Replies, Badnodes}. start_monitor(Node, Name) when is_atom(Node), is_atom(Name) -> - if node() =:= nonode@nohost, Node =/= nonode@nohost -> - Ref = make_ref(), - self() ! {'DOWN', Ref, process, {Name, Node}, noconnection}, - {Node, Ref}; - true -> - case catch erlang:monitor(process, {Name, Node}) of - {'EXIT', _} -> - %% Remote node is R6 - monitor_node(Node, true), - Node; - Ref when is_reference(Ref) -> - {Node, Ref} - end - end. + if node() =:= nonode@nohost, Node =/= nonode@nohost -> + Ref = make_ref(), + self() ! {'DOWN', Ref, process, {Name, Node}, noconnection}, + {Node, Ref}; + true -> + case catch erlang:monitor(process, {Name, Node}) of + {'EXIT', _} -> + %% Remote node is R6 + monitor_node(Node, true), + Node; + Ref when is_reference(Ref) -> + {Node, Ref} + end + end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% API helpers end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -receiveIng(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, IsHib) -> - receive - Msg -> - case Msg of - {'$gen_call', From, Request} -> - matchCallMsg(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, From, Request); - {'$gen_cast', Cast} -> - matchCastMsg(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, Cast); - {'$gen_clfn', From, MFA} -> - matchMFA(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, From, MFA, false); - {'$gen_clfs', From, MFA} -> - matchMFA(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, From, MFA, true); - {'$gen_csfn', MFA} -> - matchMFA(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, false, MFA, false); - {'$gen_csfs', MFA} -> - matchMFA(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, false, MFA, true); - {timeout, TimerRef, TimeoutName} -> - case Timers of - #{TimeoutName := {TimerRef, TimeoutMsg}} -> - NewTimer = maps:remove(TimeoutName, Timers), - matchInfoMsg(Parent, Name, Module, HibernateAfterTimeout, Debug, NewTimer, CurState, TimeoutMsg); - _ -> - matchInfoMsg(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, Msg) - end; - {system, PidFrom, Request} -> - %% 不返回但尾递归调用 system_continue/3 - sys:handle_system_msg(Request, PidFrom, Parent, ?MODULE, Debug, {Name, Module, HibernateAfterTimeout, Timers, CurState, IsHib}, IsHib); - {'EXIT', Parent, Reason} -> - terminate(exit, Reason, ?STACKTRACE(), Name, Module, Debug, Timers, CurState, Msg); - _ -> - matchInfoMsg(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, Msg) - end - after HibernateAfterTimeout -> - proc_lib:hibernate(?MODULE, wakeupFromHib, [Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState]) - end. - -matchCallMsg(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, From, Request) -> - NewDebug = ?SYS_DEBUG(Debug, Name, {in, {{call, From}, Request}}), - try - case is_tuple(Request) of - true -> - FunName = element(1, Request), - Module:FunName(Request, CurState, From); - _ -> - Module:Request(Request, CurState, From) - end - of - Result -> - handleCR(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, CurState, Result, From, false) - catch - throw:Result -> - handleCR(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, CurState, Result, From, false); - error:undef -> - try_greply(From, {error, undef}), - receiveIng(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, CurState, false); - Class:Reason:Strace -> - terminate(Class, Reason, Strace, Name, Module, NewDebug, Timers, CurState, {{call, From}, Request}) - end. - -matchCastMsg(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, Cast) -> - NewDebug = ?SYS_DEBUG(Debug, Name, {in, {cast, Cast}}), - try - case is_tuple(Cast) of - true -> - FunName = element(1, Cast), - Module:FunName(Cast, CurState); - _ -> - Module:Cast(Cast, CurState) - end - of - Result -> - handleCR(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, CurState, Result, false, false) - catch - throw:Result -> - handleCR(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, CurState, Result, false, false); - error:undef -> - receiveIng(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, CurState, false); - Class:Reason:Strace -> - terminate(Class, Reason, Strace, Name, Module, NewDebug, Timers, CurState, {cast, Cast}) - end. - -matchMFA(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, From, MFA, IsWithState) -> - NewDebug = ?SYS_DEBUG(Debug, Name, {in, {mfa, MFA}}), - try - {M, F, A} = MFA, - case IsWithState of - true -> - erlang:apply(M, F, A ++ [CurState]); - _ -> - erlang:apply(M, F, A) - end - of - Result -> - handleCR(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, CurState, Result, From, true) - catch - throw:Result -> - handleCR(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, CurState, Result, From, true); - error:undef -> - try_greply(From, {error, undef}), - receiveIng(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, CurState, false); - Class:Reason:Strace -> - terminate(Class, Reason, Strace, Name, Module, NewDebug, Timers, CurState, {mfa, MFA}) - end. - -matchInfoMsg(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, Msg) -> - NewDebug = ?SYS_DEBUG(Debug, Name, {in, {info, Msg}}), - try Module:handleInfo(Msg, CurState) of - Result -> - handleCR(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, CurState, Result, false, false) - catch - throw:Result -> - handleCR(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, CurState, Result, false, false); - Class:Reason:Strace -> - terminate(Class, Reason, Strace, Name, Module, NewDebug, Timers, CurState, {info, Msg}) - end. - -doAfterCall(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, LeftAction, Args) -> - NewDebug = ?SYS_DEBUG(Debug, Name, {in, {doAfter, Args}}), - try Module:handleAfter(Args, CurState) of - Result -> - handleAR(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, CurState, LeftAction, Result) - catch - throw:Result -> - handleAR(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, CurState, LeftAction, Result); - Class:Reason:Strace -> - terminate(Class, Reason, Strace, Name, Module, NewDebug, Timers, CurState, {doAfter, Args}) - end. - -handleCR(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, Result, From, IsAnyRet) -> - case Result of - kpS -> - receiveIng(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, false); - {reply, Reply} -> - reply(From, Reply), - NewDebug = ?SYS_DEBUG(Debug, Name, {out, Reply, From, CurState}), - receiveIng(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, CurState, false); - {mayReply, Reply} -> - case From of - false -> - receiveIng(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, false); - _ -> - greply(From, Reply), - NewDebug = ?SYS_DEBUG(Debug, Name, {out, Reply, From, CurState}), - receiveIng(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, CurState, false) - end; - {noreply, NewState} -> - receiveIng(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, NewState, false); - {reply, Reply, NewState} -> - reply(From, Reply), - NewDebug = ?SYS_DEBUG(Debug, Name, {out, Reply, From, NewState}), - receiveIng(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, NewState, false); - {mayReply, Reply, NewState} -> - case From of - false -> - receiveIng(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, NewState, false); - _ -> - greply(From, Reply), - NewDebug = ?SYS_DEBUG(Debug, Name, {out, Reply, From, NewState}), - receiveIng(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, NewState, false) - end; - {noreply, NewState, Actions} -> - loopEntry(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, NewState, listify(Actions)); - {stop, Reason, NewState} -> - terminate(exit, Reason, ?STACKTRACE(), Name, Module, Debug, Timers, NewState, {return, stop}); - {reply, Reply, NewState, Actions} -> - reply(From, Reply), - NewDebug = ?SYS_DEBUG(Debug, Name, {out, Reply, From, NewState}), - loopEntry(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, NewState, listify(Actions)); - {mayReply, Reply, NewState, Actions} -> - case From of - false -> - loopEntry(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, NewState, listify(Actions)); - _ -> - - greply(From, Reply), - NewDebug = ?SYS_DEBUG(Debug, Name, {out, Reply, From, NewState}), - loopEntry(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, NewState, listify(Actions)) - end; - {stopReply, Reason, Reply, NewState} -> - NewDebug = ?SYS_DEBUG(Debug, Name, {out, Reply, From, NewState}), - try - terminate(exit, Reason, ?STACKTRACE(), Name, Module, NewDebug, Timers, NewState, {return, stop_reply}) - after - _ = reply(From, Reply) - end; - _AnyRet -> - case IsAnyRet of - true -> - receiveIng(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, false); - _ -> - terminate(exit, bad_ret, ?STACKTRACE(), Name, Module, Debug, Timers, CurState, {return, _AnyRet}) - end - end. - -handleAR(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, LeftAction, Result) -> - case Result of - kpS -> - loopEntry(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, LeftAction); - {noreply, NewState} -> - loopEntry(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, NewState, LeftAction); - {noreply, NewState, Actions} -> - loopEntry(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, NewState, listify(Actions) ++ LeftAction); - {stop, Reason, NewState} -> - terminate(exit, Reason, ?STACKTRACE(), Name, Module, Debug, Timers, NewState, {return, stop_reply}) - end. +receiveIng(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, IsHib) -> + receive + Msg -> + case Msg of + {'$gen_call', From, Request} -> + matchCallMsg(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, From, Request); + {'$gen_cast', Cast} -> + matchCastMsg(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Cast); + {'$gen_clfn', From, MFA} -> + matchMFA(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, From, MFA, false); + {'$gen_clfs', From, MFA} -> + matchMFA(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, From, MFA, true); + {'$gen_csfn', MFA} -> + matchMFA(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, false, MFA, false); + {'$gen_csfs', MFA} -> + matchMFA(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, false, MFA, true); + {timeout, TimerRef, TimeoutName} -> + case Timers of + #{TimeoutName := {TimerRef, TimeoutMsg}} -> + NewTimer = maps:remove(TimeoutName, Timers), + matchInfoMsg(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, NewTimer, CurState, TimeoutMsg); + _ -> + matchInfoMsg(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Msg) + end; + {system, PidFrom, Request} -> + %% 不返回但尾递归调用 system_continue/3 + sys:handle_system_msg(Request, PidFrom, Parent, ?MODULE, Debug, {Name, Module, GbhOpts, HibernateAfterTimeout, Timers, CurState, IsHib}, IsHib); + {'EXIT', Parent, Reason} -> + terminate(exit, Reason, ?STACKTRACE(), Name, Module, Debug, Timers, CurState, Msg); + _ -> + matchInfoMsg(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Msg) + end + after HibernateAfterTimeout -> + proc_lib:hibernate(?MODULE, wakeupFromHib, [Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState]) + end. + +matchCallMsg(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, From, Request) -> + ?SYS_DEBUG(Debug, Name, {in, {{call, From}, Request}}), + try + case is_tuple(Request) of + true -> + FunName = element(1, Request), + Module:FunName(Request, CurState, From); + _ -> + Module:Request(Request, CurState, From) + end + of + Result -> + handleCR(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Result, From, false) + catch + throw:Result -> + handleCR(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Result, From, false); + error:undef -> + try_greply(From, {error, undef}), + receiveIng(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, false); + Class:Reason:Strace -> + try_greply(From, {error, {inner_error, {Class, Reason, Strace}}}), + innerError(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, {{call, From}, Request}, Class, Reason, Strace) + end. + +matchCastMsg(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Cast) -> + ?SYS_DEBUG(Debug, Name, {in, {cast, Cast}}), + try + case is_tuple(Cast) of + true -> + FunName = element(1, Cast), + Module:FunName(Cast, CurState); + _ -> + Module:Cast(Cast, CurState) + end + of + Result -> + handleCR(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Result, false, false) + catch + throw:Result -> + handleCR(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Result, false, false); + error:undef -> + receiveIng(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, false); + Class:Reason:Strace -> + innerError(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, {cast, Cast}, Class, Reason, Strace) + end. + +matchMFA(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, From, MFA, IsWithState) -> + ?SYS_DEBUG(Debug, Name, {in, {mfa, MFA}}), + try + {M, F, A} = MFA, + case IsWithState of + true -> + erlang:apply(M, F, A ++ [CurState]); + _ -> + erlang:apply(M, F, A) + end + of + Result -> + handleCR(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Result, From, true) + catch + throw:Result -> + handleCR(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Result, From, true); + error:undef -> + try_greply(From, {error, undef}), + receiveIng(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, false); + Class:Reason:Strace -> + innerError(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, {mfa, MFA}, Class, Reason, Strace) + end. + +matchInfoMsg(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Msg) -> + ?SYS_DEBUG(Debug, Name, {in, {info, Msg}}), + try Module:handleInfo(Msg, CurState) of + Result -> + handleCR(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Result, false, false) + catch + throw:Result -> + handleCR(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Result, false, false); + Class:Reason:Strace -> + innerError(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, {info, Msg}, Class, Reason, Strace) + end. + +doAfterCall(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, LeftAction, Args) -> + ?SYS_DEBUG(Debug, Name, {in, {doAfter, Args}}), + try Module:handleAfter(Args, CurState) of + Result -> + handleAR(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, LeftAction, Result) + catch + throw:Result -> + handleAR(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, LeftAction, Result); + Class:Reason:Strace -> + innerError(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, {doAfter, Args}, Class, Reason, Strace) + end. + +handleCR(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Result, From, IsAnyRet) -> + case Result of + kpS -> + receiveIng(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, false); + {reply, Reply} -> + reply(From, Reply), + ?SYS_DEBUG(Debug, Name, {out, Reply, From, CurState}), + receiveIng(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, false); + {mayReply, Reply} -> + case From of + false -> + receiveIng(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, false); + _ -> + greply(From, Reply), + ?SYS_DEBUG(Debug, Name, {out, Reply, From, CurState}), + receiveIng(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, false) + end; + {noreply, NewState} -> + receiveIng(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, NewState, false); + {reply, Reply, NewState} -> + reply(From, Reply), + ?SYS_DEBUG(Debug, Name, {out, Reply, From, NewState}), + receiveIng(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, NewState, false); + {mayReply, Reply, NewState} -> + case From of + false -> + receiveIng(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, NewState, false); + _ -> + greply(From, Reply), + ?SYS_DEBUG(Debug, Name, {out, Reply, From, NewState}), + receiveIng(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, NewState, false) + end; + {noreply, NewState, Actions} -> + loopEntry(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, NewState, listify(Actions)); + {stop, Reason, NewState} -> + terminate(exit, Reason, ?STACKTRACE(), Name, Module, Debug, Timers, NewState, {return, stop}); + {reply, Reply, NewState, Actions} -> + reply(From, Reply), + ?SYS_DEBUG(Debug, Name, {out, Reply, From, NewState}), + loopEntry(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, NewState, listify(Actions)); + {mayReply, Reply, NewState, Actions} -> + case From of + false -> + loopEntry(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, NewState, listify(Actions)); + _ -> + + greply(From, Reply), + ?SYS_DEBUG(Debug, Name, {out, Reply, From, NewState}), + loopEntry(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, NewState, listify(Actions)) + end; + {stopReply, Reason, Reply, NewState} -> + ?SYS_DEBUG(Debug, Name, {out, Reply, From, NewState}), + try + terminate(exit, Reason, ?STACKTRACE(), Name, Module, Debug, Timers, NewState, {return, stop_reply}) + after + _ = reply(From, Reply) + end; + _AnyRet -> + case IsAnyRet of + true -> + receiveIng(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, false); + _ -> + innerError(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, {return, _AnyRet}, error, bad_ret, ?STACKTRACE()) + end + end. + +handleAR(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, LeftAction, Result) -> + case Result of + kpS -> + loopEntry(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, LeftAction); + {noreply, NewState} -> + loopEntry(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, NewState, LeftAction); + {noreply, NewState, Actions} -> + loopEntry(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, NewState, listify(Actions) ++ LeftAction); + {stop, Reason, NewState} -> + terminate(exit, Reason, ?STACKTRACE(), Name, Module, Debug, Timers, NewState, {return, stop_reply}) + end. %% loopParseActionsList doParseAL([], _Name, Debug, IsHib, DoAfter, Timers) -> - {Debug, IsHib, DoAfter, Timers}; + {Debug, IsHib, DoAfter, Timers}; doParseAL([OneAction | LeftActions], Name, Debug, IsHib, DoAfter, Timers) -> - case OneAction of - hibernate -> - doParseAL(LeftActions, Name, Debug, true, DoAfter, Timers); - {'doAfter', _Args} -> - doParseAL(LeftActions, Name, Debug, IsHib, OneAction, Timers); - {'nTimeout', TimeoutName, Time, TimeoutMsg, Options} -> - case Time of - infinity -> - NewTimers = doCancelTimer(TimeoutName, Timers), - doParseAL(LeftActions, Name, Debug, IsHib, DoAfter, NewTimers); - _ -> - TimerRef = erlang:start_timer(Time, self(), TimeoutName, Options), - NewDebug = ?SYS_DEBUG(Debug, Name, {start_timer, {TimeoutName, Time, TimeoutMsg, Options}}), - NewTimers = doRegisterTimer(TimeoutName, TimerRef, TimeoutMsg, Timers), - doParseAL(LeftActions, Name, NewDebug, IsHib, DoAfter, NewTimers) - end; - {'nTimeout', TimeoutName, Time, TimeoutMsg} -> - case Time of - infinity -> - NewTimers = doCancelTimer(TimeoutName, Timers), - doParseAL(LeftActions, Name, Debug, IsHib, DoAfter, NewTimers); - _ -> - TimerRef = erlang:start_timer(Time, self(), TimeoutName), - NewDebug = ?SYS_DEBUG(Debug, Name, {start_timer, {TimeoutName, Time, TimeoutMsg, []}}), - NewTimers = doRegisterTimer(TimeoutName, TimerRef, TimeoutMsg, Timers), - doParseAL(LeftActions, Name, NewDebug, IsHib, DoAfter, NewTimers) - end; - {'uTimeout', TimeoutName, NewTimeoutMsg} -> - NewTimers = doUpdateTimer(TimeoutName, NewTimeoutMsg, Timers), - doParseAL(LeftActions, Name, Debug, IsHib, DoAfter, NewTimers); - {'cTimeout', TimeoutName} -> - NewTimers = doCancelTimer(TimeoutName, Timers), - doParseAL(LeftActions, Name, Debug, IsHib, DoAfter, NewTimers); - infinity -> - doParseAL(LeftActions, Name, Debug, IsHib, DoAfter, Timers); - Timeout when is_integer(Timeout) -> - erlang:send_after(Timeout, self(), timeout), - NewDebug = ?SYS_DEBUG(Debug, Name, {start_timer, {timeout, Timeout, timeout, []}}), - doParseAL(LeftActions, Name, NewDebug, IsHib, DoAfter, Timers); - _ -> - {error, {bad_ActionType, OneAction}} - end. + case OneAction of + hibernate -> + doParseAL(LeftActions, Name, Debug, true, DoAfter, Timers); + {'doAfter', _Args} -> + doParseAL(LeftActions, Name, Debug, IsHib, OneAction, Timers); + {'nTimeout', TimeoutName, Time, TimeoutMsg, Options} -> + case Time of + infinity -> + NewTimers = doCancelTimer(TimeoutName, Timers), + doParseAL(LeftActions, Name, Debug, IsHib, DoAfter, NewTimers); + _ -> + TimerRef = erlang:start_timer(Time, self(), TimeoutName, Options), + ?SYS_DEBUG(Debug, Name, {start_timer, {TimeoutName, Time, TimeoutMsg, Options}}), + NewTimers = doRegisterTimer(TimeoutName, TimerRef, TimeoutMsg, Timers), + doParseAL(LeftActions, Name, Debug, IsHib, DoAfter, NewTimers) + end; + {'nTimeout', TimeoutName, Time, TimeoutMsg} -> + case Time of + infinity -> + NewTimers = doCancelTimer(TimeoutName, Timers), + doParseAL(LeftActions, Name, Debug, IsHib, DoAfter, NewTimers); + _ -> + TimerRef = erlang:start_timer(Time, self(), TimeoutName), + ?SYS_DEBUG(Debug, Name, {start_timer, {TimeoutName, Time, TimeoutMsg, []}}), + NewTimers = doRegisterTimer(TimeoutName, TimerRef, TimeoutMsg, Timers), + doParseAL(LeftActions, Name, Debug, IsHib, DoAfter, NewTimers) + end; + {'uTimeout', TimeoutName, NewTimeoutMsg} -> + NewTimers = doUpdateTimer(TimeoutName, NewTimeoutMsg, Timers), + doParseAL(LeftActions, Name, Debug, IsHib, DoAfter, NewTimers); + {'cTimeout', TimeoutName} -> + NewTimers = doCancelTimer(TimeoutName, Timers), + doParseAL(LeftActions, Name, Debug, IsHib, DoAfter, NewTimers); + infinity -> + doParseAL(LeftActions, Name, Debug, IsHib, DoAfter, Timers); + Timeout when is_integer(Timeout) -> + erlang:send_after(Timeout, self(), timeout), + ?SYS_DEBUG(Debug, Name, {start_timer, {timeout, Timeout, timeout, []}}), + doParseAL(LeftActions, Name, Debug, IsHib, DoAfter, Timers); + _ -> + {error, {bad_ActionType, OneAction}} + end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% timer deal start %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - doRegisterTimer(TimeoutType, NewTimerRef, TimeoutMsg, Timers) -> - case Timers of - #{TimeoutType := {OldTimerRef, _OldTimeMsg}} -> - justCancelTimer(TimeoutType, OldTimerRef), - Timers#{TimeoutType := {NewTimerRef, TimeoutMsg}}; - _ -> - Timers#{TimeoutType => {NewTimerRef, TimeoutMsg}} - end. + case Timers of + #{TimeoutType := {OldTimerRef, _OldTimeMsg}} -> + justCancelTimer(TimeoutType, OldTimerRef), + Timers#{TimeoutType := {NewTimerRef, TimeoutMsg}}; + _ -> + Timers#{TimeoutType => {NewTimerRef, TimeoutMsg}} + end. doCancelTimer(TimeoutType, Timers) -> - case Timers of - #{TimeoutType := {TimerRef, _TimeoutMsg}} -> - cancelTimer(TimeoutType, TimerRef, Timers); - _ -> - Timers - end. + case Timers of + #{TimeoutType := {TimerRef, _TimeoutMsg}} -> + cancelTimer(TimeoutType, TimerRef, Timers); + _ -> + Timers + end. doUpdateTimer(TimeoutType, Timers, TimeoutMsg) -> - case Timers of - #{TimeoutType := {TimerRef, _OldTimeoutMsg}} -> - Timers#{TimeoutType := {TimerRef, TimeoutMsg}}; - _ -> - Timers - end. + case Timers of + #{TimeoutType := {TimerRef, _OldTimeoutMsg}} -> + Timers#{TimeoutType := {TimerRef, TimeoutMsg}}; + _ -> + Timers + end. justCancelTimer(TimeoutType, TimerRef) -> - case erlang:cancel_timer(TimerRef) of - false -> - %% 找不到计时器,我们还没有看到超时消息 - receive - {timeout, TimerRef, TimeoutType} -> - %% 丢弃该超时消息 - ok - after 0 -> - ok - end; - _ -> - %% Timer 已经运行了 - ok - end. + case erlang:cancel_timer(TimerRef) of + false -> + %% 找不到计时器,我们还没有看到超时消息 + receive + {timeout, TimerRef, TimeoutType} -> + %% 丢弃该超时消息 + ok + after 0 -> + ok + end; + _ -> + %% Timer 已经运行了 + ok + end. cancelTimer(TimeoutType, TimerRef, Timers) -> - case erlang:cancel_timer(TimerRef) of - false -> % 找不到计时器,我们还没有看到超时消息 - receive - {timeout, TimerRef, TimeoutType} -> - ok % 丢弃该超时消息 - after 0 -> - ok - end; - _ -> - ok % Timer 已经运行了 - end, - maps:remove(TimeoutType, Timers). + case erlang:cancel_timer(TimerRef) of + false -> % 找不到计时器,我们还没有看到超时消息 + receive + {timeout, TimerRef, TimeoutType} -> + ok % 丢弃该超时消息 + after 0 -> + ok + end; + _ -> + ok % Timer 已经运行了 + end, + maps:remove(TimeoutType, Timers). listify(Item) when is_list(Item) -> - Item; + Item; listify(Item) -> - [Item]. + [Item]. listHib(false) -> - []; + []; listHib(_) -> - [hibernate]. + [hibernate]. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% timer deal end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - +innerError(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, MsgEvent, Class, Reason, Stacktrace) -> + case GbhOpts of + #gbhOpts{daemon = true} -> + error_msg({innerError, {Class, Reason, Stacktrace}}, Name, undefined, MsgEvent, Module, Debug, CurState), + case erlang:function_exported(Module, handleError, 2) of + true -> + try Module:handleError({Class, Reason, Stacktrace}, CurState) of + Result -> + handleCR(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Result, false, false) + catch + throw:Result -> + handleCR(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Result, false, false); + IClass:IReason:IStrace -> + error_msg({handleError, {IClass, IReason, IStrace}}, Name, undefined, {{Class, Reason, Stacktrace}}, Module, Debug, CurState), + kpS + end; + false -> + kpS + end; + _ -> + terminate(Class, Reason, Stacktrace, Name, Module, Debug, Timers, CurState, MsgEvent) + end. %%% --------------------------------------------------- %%% Terminate the server. @@ -1046,81 +1067,97 @@ listHib(_) -> %%% for exits. %%% --------------------------------------------------- terminate(Class, Reason, Stacktrace, Name, Module, Debug, _Timers, CurState, MsgEvent) -> - Reply = try_terminate(Module, terminate_reason(Class, Reason, Stacktrace), CurState), - case Reply of - {'EXIT', C, R, S} -> - error_info({R, S}, Name, undefined, MsgEvent, Module, Debug, CurState), - erlang:raise(C, R, S); - _ -> - case {Class, Reason} of - {exit, normal} -> ok; - {exit, shutdown} -> ok; - {exit, {shutdown, _}} -> ok; - _ -> - error_info(Reason, Name, undefined, MsgEvent, Module, Debug, CurState) - end - end, - case Stacktrace of - [] -> - erlang:Class(Reason); - _ -> - erlang:raise(Class, Reason, Stacktrace) - end. + Reply = try_terminate(Module, terminate_reason(Class, Reason, Stacktrace), CurState), + case Reply of + {'EXIT', C, R, S} -> + error_info({R, S}, Name, undefined, MsgEvent, Module, Debug, CurState), + erlang:raise(C, R, S); + _ -> + case {Class, Reason} of + {exit, normal} -> ok; + {exit, shutdown} -> ok; + {exit, {shutdown, _}} -> ok; + _ -> + error_info(Reason, Name, undefined, MsgEvent, Module, Debug, CurState) + end + end, + case Stacktrace of + [] -> + erlang:Class(Reason); + _ -> + erlang:raise(Class, Reason, Stacktrace) + end. try_terminate(Mod, Reason, State) -> - case erlang:function_exported(Mod, terminate, 2) of - true -> - try - {ok, Mod:terminate(Reason, State)} - catch - throw:Ret -> - {ok, Ret}; - Class:Reason:Strace -> - {'EXIT', Class, Reason, Strace} - end; - false -> - {ok, ok} - end. + case erlang:function_exported(Mod, terminate, 2) of + true -> + try + {ok, Mod:terminate(Reason, State)} + catch + throw:Ret -> + {ok, Ret}; + Class:Reason:Strace -> + {'EXIT', Class, Reason, Strace} + end; + false -> + {ok, ok} + end. terminate_reason(error, Reason, Stacktrace) -> {Reason, Stacktrace}; terminate_reason(exit, Reason, _Stacktrace) -> Reason. error_info(_Reason, application_controller, _From, _Msg, _Mod, _State, _Debug) -> - %% OTP-5811 Don't send an error report if it's the system process - %% application_controller which is terminating - let init take care - %% of it instead - ok; + %% OTP-5811 Don't send an error report if it's the system process + %% application_controller which is terminating - let init take care + %% of it instead + ok; error_info(Reason, Name, From, Msg, Module, Debug, State) -> - Log = sys:get_log(Debug), - ?LOG_ERROR(#{label => {gen_apu, terminate}, - name => Name, - last_message => Msg, - state => format_status(terminate, Module, get(), State), - log => format_log_state(Module, Log), - reason => Reason, - client_info => client_stacktrace(From)}, - #{ - domain => [otp], - report_cb => fun gen_apu:format_log/2, - error_logger => #{tag => error, report_cb => fun gen_apu:format_log/1} - }), - ok. + Log = sys:get_log(Debug), + ?LOG_ERROR(#{label => {gen_apu, terminate}, + name => Name, + last_message => Msg, + state => format_status(terminate, Module, get(), State), + log => format_log_state(Module, Log), + reason => Reason, + client_info => client_stacktrace(From)}, + #{ + domain => [otp], + report_cb => fun gen_apu:format_log/2, + error_logger => #{tag => error, report_cb => fun gen_apu:format_log/1} + }), + ok. + +error_msg(Reason, Name, From, Msg, Module, Debug, State) -> + Log = sys:get_log(Debug), + ?LOG_ERROR(#{label => {gen_apu, inner_error}, + name => Name, + last_message => Msg, + state => format_status(inner_error, Module, get(), State), + log => format_log_state(Module, Log), + reason => Reason, + client_info => client_stacktrace(From)}, + #{ + domain => [otp], + report_cb => fun gen_apu:format_log/2, + error_logger => #{tag => error, report_cb => fun gen_apu:format_log/1} + }), + ok. client_stacktrace(undefined) -> - undefined; + undefined; client_stacktrace({From, _Tag}) -> - client_stacktrace(From); + client_stacktrace(From); client_stacktrace(From) when is_pid(From), node(From) =:= node() -> - case process_info(From, [current_stacktrace, registered_name]) of - undefined -> - {From, dead}; - [{current_stacktrace, Stacktrace}, {registered_name, []}] -> - {From, {From, Stacktrace}}; - [{current_stacktrace, Stacktrace}, {registered_name, Name}] -> - {From, {Name, Stacktrace}} - end; + case process_info(From, [current_stacktrace, registered_name]) of + undefined -> + {From, dead}; + [{current_stacktrace, Stacktrace}, {registered_name, []}] -> + {From, {From, Stacktrace}}; + [{current_stacktrace, Stacktrace}, {registered_name, Name}] -> + {From, {Name, Stacktrace}} + end; client_stacktrace(From) when is_pid(From) -> - {From, remote}. + {From, remote}. %% format_log/1 is the report callback used by Logger handler @@ -1129,221 +1166,221 @@ client_stacktrace(From) when is_pid(From) -> %% return {Format,Args} compatible with the arguments in this module's %% calls to error_logger prior to OTP-21.0. format_log(Report) -> - Depth = error_logger:get_format_depth(), - FormatOpts = #{chars_limit => unlimited, - depth => Depth, - single_line => false, - encoding => utf8}, - format_log_multi(limit_report(Report, Depth), FormatOpts). + Depth = error_logger:get_format_depth(), + FormatOpts = #{chars_limit => unlimited, + depth => Depth, + single_line => false, + encoding => utf8}, + format_log_multi(limit_report(Report, Depth), FormatOpts). limit_report(Report, unlimited) -> - Report; + Report; limit_report(#{label := {gen_apu, terminate}, - last_message := Msg, - state := State, - log := Log, - reason := Reason, - client_info := Client} = Report, - Depth) -> - Report#{ - last_message => io_lib:limit_term(Msg, Depth), - state => io_lib:limit_term(State, Depth), - log => [io_lib:limit_term(L, Depth) || L <- Log], - reason => io_lib:limit_term(Reason, Depth), - client_info => limit_client_report(Client, Depth) - }; + last_message := Msg, + state := State, + log := Log, + reason := Reason, + client_info := Client} = Report, + Depth) -> + Report#{ + last_message => io_lib:limit_term(Msg, Depth), + state => io_lib:limit_term(State, Depth), + log => [io_lib:limit_term(L, Depth) || L <- Log], + reason => io_lib:limit_term(Reason, Depth), + client_info => limit_client_report(Client, Depth) + }; limit_report(#{label := {gen_apu, no_handle_info}, - message := Msg} = Report, Depth) -> - Report#{message => io_lib:limit_term(Msg, Depth)}. + message := Msg} = Report, Depth) -> + Report#{message => io_lib:limit_term(Msg, Depth)}. limit_client_report({From, {Name, Stacktrace}}, Depth) -> - {From, {Name, io_lib:limit_term(Stacktrace, Depth)}}; + {From, {Name, io_lib:limit_term(Stacktrace, Depth)}}; limit_client_report(Client, _) -> - Client. + Client. %% format_log/2 is the report callback for any Logger handler, except %% error_logger. format_log(Report, FormatOpts0) -> - Default = #{chars_limit => unlimited, - depth => unlimited, - single_line => false, - encoding => utf8}, - FormatOpts = maps:merge(Default, FormatOpts0), - IoOpts = - case FormatOpts of - #{chars_limit := unlimited} -> - []; - #{chars_limit := Limit} -> - [{chars_limit, Limit}] - end, - {Format, Args} = format_log_single(Report, FormatOpts), - io_lib:format(Format, Args, IoOpts). + Default = #{chars_limit => unlimited, + depth => unlimited, + single_line => false, + encoding => utf8}, + FormatOpts = maps:merge(Default, FormatOpts0), + IoOpts = + case FormatOpts of + #{chars_limit := unlimited} -> + []; + #{chars_limit := Limit} -> + [{chars_limit, Limit}] + end, + {Format, Args} = format_log_single(Report, FormatOpts), + io_lib:format(Format, Args, IoOpts). format_log_single(#{label := {gen_apu, terminate}, - name := Name, - last_message := Msg, - state := State, - log := Log, - reason := Reason, - client_info := Client}, - #{single_line := true, depth := Depth} = FormatOpts) -> - P = p(FormatOpts), - Format1 = lists:append(["Generic server ", P, " terminating. Reason: ", P, - ". Last message: ", P, ". State: ", P, "."]), - {ServerLogFormat, ServerLogArgs} = format_server_log_single(Log, FormatOpts), - {ClientLogFormat, ClientLogArgs} = format_client_log_single(Client, FormatOpts), - - Args1 = - case Depth of - unlimited -> - [Name, fix_reason(Reason), Msg, State]; - _ -> - [Name, Depth, fix_reason(Reason), Depth, Msg, Depth, State, Depth] - end, - {Format1 ++ ServerLogFormat ++ ClientLogFormat, - Args1 ++ ServerLogArgs ++ ClientLogArgs}; + name := Name, + last_message := Msg, + state := State, + log := Log, + reason := Reason, + client_info := Client}, + #{single_line := true, depth := Depth} = FormatOpts) -> + P = p(FormatOpts), + Format1 = lists:append(["Generic server ", P, " terminating. Reason: ", P, + ". Last message: ", P, ". State: ", P, "."]), + {ServerLogFormat, ServerLogArgs} = format_server_log_single(Log, FormatOpts), + {ClientLogFormat, ClientLogArgs} = format_client_log_single(Client, FormatOpts), + + Args1 = + case Depth of + unlimited -> + [Name, fix_reason(Reason), Msg, State]; + _ -> + [Name, Depth, fix_reason(Reason), Depth, Msg, Depth, State, Depth] + end, + {Format1 ++ ServerLogFormat ++ ClientLogFormat, + Args1 ++ ServerLogArgs ++ ClientLogArgs}; format_log_single(#{label := {gen_apu, no_handle_info}, - module := Module, - message := Msg}, - #{single_line := true, depth := Depth} = FormatOpts) -> - P = p(FormatOpts), - Format = lists:append(["Undefined handle_info in ", P, - ". Unhandled message: ", P, "."]), - Args = - case Depth of - unlimited -> - [Module, Msg]; - _ -> - [Module, Depth, Msg, Depth] - end, - {Format, Args}; + module := Module, + message := Msg}, + #{single_line := true, depth := Depth} = FormatOpts) -> + P = p(FormatOpts), + Format = lists:append(["Undefined handle_info in ", P, + ". Unhandled message: ", P, "."]), + Args = + case Depth of + unlimited -> + [Module, Msg]; + _ -> + [Module, Depth, Msg, Depth] + end, + {Format, Args}; format_log_single(Report, FormatOpts) -> - format_log_multi(Report, FormatOpts). + format_log_multi(Report, FormatOpts). format_log_multi(#{label := {gen_apu, terminate}, - name := Name, - last_message := Msg, - state := State, - log := Log, - reason := Reason, - client_info := Client}, - #{depth := Depth} = FormatOpts) -> - Reason1 = fix_reason(Reason), - {ClientFmt, ClientArgs} = format_client_log(Client, FormatOpts), - P = p(FormatOpts), - Format = - lists:append( - ["** Generic server ", P, " terminating \n" - "** Last message in was ", P, "~n" - "** When Server state == ", P, "~n" - "** Reason for termination ==~n** ", P, "~n"] ++ - case Log of - [] -> []; - _ -> ["** Log ==~n** [" | - lists:join(",~n ", lists:duplicate(length(Log), P))] ++ - ["]~n"] - end) ++ ClientFmt, - Args = - case Depth of - unlimited -> - [Name, Msg, State, Reason1] ++ Log ++ ClientArgs; - _ -> - [Name, Depth, Msg, Depth, State, Depth, Reason1, Depth] ++ - case Log of - [] -> []; - _ -> lists:flatmap(fun(L) -> [L, Depth] end, Log) - end ++ ClientArgs - end, - {Format, Args}; + name := Name, + last_message := Msg, + state := State, + log := Log, + reason := Reason, + client_info := Client}, + #{depth := Depth} = FormatOpts) -> + Reason1 = fix_reason(Reason), + {ClientFmt, ClientArgs} = format_client_log(Client, FormatOpts), + P = p(FormatOpts), + Format = + lists:append( + ["** Generic server ", P, " terminating \n" + "** Last message in was ", P, "~n" + "** When Server state == ", P, "~n" + "** Reason for termination ==~n** ", P, "~n"] ++ + case Log of + [] -> []; + _ -> ["** Log ==~n** [" | + lists:join(",~n ", lists:duplicate(length(Log), P))] ++ + ["]~n"] + end) ++ ClientFmt, + Args = + case Depth of + unlimited -> + [Name, Msg, State, Reason1] ++ Log ++ ClientArgs; + _ -> + [Name, Depth, Msg, Depth, State, Depth, Reason1, Depth] ++ + case Log of + [] -> []; + _ -> lists:flatmap(fun(L) -> [L, Depth] end, Log) + end ++ ClientArgs + end, + {Format, Args}; format_log_multi(#{label := {gen_apu, no_handle_info}, - module := Module, - message := Msg}, - #{depth := Depth} = FormatOpts) -> - P = p(FormatOpts), - Format = - "** Undefined handle_info in ~p~n" - "** Unhandled message: " ++ P ++ "~n", - Args = - case Depth of - unlimited -> - [Module, Msg]; - _ -> - [Module, Msg, Depth] - end, - {Format, Args}. + module := Module, + message := Msg}, + #{depth := Depth} = FormatOpts) -> + P = p(FormatOpts), + Format = + "** Undefined handle_info in ~p~n" + "** Unhandled message: " ++ P ++ "~n", + Args = + case Depth of + unlimited -> + [Module, Msg]; + _ -> + [Module, Msg, Depth] + end, + {Format, Args}. fix_reason({undef, [{M, F, A, L} | MFAs]} = Reason) -> - 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 -> - Reason; - false -> - {'function not exported', [{M, F, A, L} | MFAs]} - end - end; + 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 -> + Reason; + false -> + {'function not exported', [{M, F, A, L} | MFAs]} + end + end; fix_reason(Reason) -> - Reason. + Reason. format_server_log_single([], _) -> - {"", []}; + {"", []}; format_server_log_single(Log, FormatOpts) -> - Args = - case maps:get(depth, FormatOpts) of - unlimited -> - [Log]; - Depth -> - [Log, Depth] - end, - {" Log: " ++ p(FormatOpts), Args}. + Args = + case maps:get(depth, FormatOpts) of + unlimited -> + [Log]; + Depth -> + [Log, Depth] + end, + {" Log: " ++ p(FormatOpts), Args}. format_client_log_single(undefined, _) -> - {"", []}; + {"", []}; format_client_log_single({From, dead}, _) -> - {" Client ~0p is dead.", [From]}; + {" Client ~0p is dead.", [From]}; format_client_log_single({From, remote}, _) -> - {" Client ~0p is remote on node ~0p.", [From, node(From)]}; + {" Client ~0p is remote on node ~0p.", [From, node(From)]}; format_client_log_single({_From, {Name, Stacktrace0}}, FormatOpts) -> - P = p(FormatOpts), - %% Minimize the stacktrace a bit for single line reports. This is - %% hopefully enough to point out the position. - Stacktrace = lists:sublist(Stacktrace0, 4), - Args = - case maps:get(depth, FormatOpts) of - unlimited -> - [Name, Stacktrace]; - Depth -> - [Name, Depth, Stacktrace, Depth] - end, - {" Client " ++ P ++ " stacktrace: " ++ P ++ ".", Args}. + P = p(FormatOpts), + %% Minimize the stacktrace a bit for single line reports. This is + %% hopefully enough to point out the position. + Stacktrace = lists:sublist(Stacktrace0, 4), + Args = + case maps:get(depth, FormatOpts) of + unlimited -> + [Name, Stacktrace]; + Depth -> + [Name, Depth, Stacktrace, Depth] + end, + {" Client " ++ P ++ " stacktrace: " ++ P ++ ".", Args}. format_client_log(undefined, _) -> - {"", []}; + {"", []}; format_client_log({From, dead}, _) -> - {"** Client ~p is dead~n", [From]}; + {"** Client ~p is dead~n", [From]}; format_client_log({From, remote}, _) -> - {"** Client ~p is remote on node ~p~n", [From, node(From)]}; + {"** Client ~p is remote on node ~p~n", [From, node(From)]}; format_client_log({_From, {Name, Stacktrace}}, FormatOpts) -> - P = p(FormatOpts), - Format = lists:append(["** Client ", P, " stacktrace~n", - "** ", P, "~n"]), - Args = - case maps:get(depth, FormatOpts) of - unlimited -> - [Name, Stacktrace]; - Depth -> - [Name, Depth, Stacktrace, Depth] - end, - {Format, Args}. + P = p(FormatOpts), + Format = lists:append(["** Client ", P, " stacktrace~n", + "** ", P, "~n"]), + Args = + case maps:get(depth, FormatOpts) of + unlimited -> + [Name, Stacktrace]; + Depth -> + [Name, Depth, Stacktrace, Depth] + end, + {Format, Args}. p(#{single_line := Single, depth := Depth, encoding := Enc}) -> - "~" ++ single(Single) ++ mod(Enc) ++ p(Depth); + "~" ++ single(Single) ++ mod(Enc) ++ p(Depth); p(unlimited) -> - "p"; + "p"; p(_Depth) -> - "P". + "P". single(true) -> "0"; single(false) -> "". @@ -1355,64 +1392,64 @@ mod(_) -> "t". %% Status information %%----------------------------------------------------------------- format_status(Opt, StatusData) -> - [PDict, SysState, Parent, Debug, {Name, Module, _HibernateAfterTimeout, _Timers, CurState, _IsHib}] = StatusData, - Header = gen:format_status_header("Status for generic server", Name), - Log = sys:get_log(Debug), - Specific = - case format_status(Opt, Module, PDict, CurState) of - S when is_list(S) -> S; - S -> [S] - end, - [{header, Header}, - {data, [{"Status", SysState}, - {"Parent", Parent}, - {"Logged events", format_log_state(Module, Log)}]} | - Specific]. + [PDict, SysState, Parent, Debug, {Name, Module, _HibernateAfterTimeout, _Timers, CurState, _IsHib}] = StatusData, + Header = gen:format_status_header("Status for generic server", Name), + Log = sys:get_log(Debug), + Specific = + case format_status(Opt, Module, PDict, CurState) of + S when is_list(S) -> S; + S -> [S] + end, + [{header, Header}, + {data, [{"Status", SysState}, + {"Parent", Parent}, + {"Logged events", format_log_state(Module, Log)}]} | + Specific]. format_log_state(Module, Log) -> - [case Event of - {out, Msg, From, State} -> - {out, Msg, From, format_status(terminate, Module, get(), State)}; - {noreply, State} -> - {noreply, format_status(terminate, Module, get(), State)}; - _ -> Event - end || Event <- Log]. + [case Event of + {out, Msg, From, State} -> + {out, Msg, From, format_status(terminate, Module, get(), State)}; + {noreply, State} -> + {noreply, format_status(terminate, Module, get(), State)}; + _ -> Event + end || Event <- Log]. format_status(Opt, Module, PDict, State) -> - DefStatus = - case Opt of - terminate -> State; - _ -> [{data, [{"State", State}]}] - end, - case erlang:function_exported(Module, format_status, 2) of - true -> - case catch Module:formatStatus(Opt, [PDict, State]) of - {'EXIT', _} -> DefStatus; - Else -> Else - end; - _ -> - DefStatus - end. + DefStatus = + case Opt of + terminate -> State; + _ -> [{data, [{"State", State}]}] + end, + case erlang:function_exported(Module, format_status, 2) of + true -> + case catch Module:formatStatus(Opt, [PDict, State]) of + {'EXIT', _} -> DefStatus; + Else -> Else + end; + _ -> + DefStatus + end. %%----------------------------------------------------------------- %% Format debug messages. Print them as the call-back module sees %% them, not as the real erlang messages. Use trace for that. %%----------------------------------------------------------------- print_event(Dev, {in, Msg}, Name) -> - case Msg of - {{call, {From, _Tag}}, Call} -> - io:format(Dev, "*DBG* ~tp got call ~tp from ~tw~n", - [Name, Call, From]); - {cast, Cast} -> - io:format(Dev, "*DBG* ~tp got cast ~tp~n", - [Name, Cast]); - _ -> - io:format(Dev, "*DBG* ~tp got ~tp~n", [Name, Msg]) - end; + case Msg of + {{call, {From, _Tag}}, Call} -> + io:format(Dev, "*DBG* ~tp got call ~tp from ~tw~n", + [Name, Call, From]); + {cast, Cast} -> + io:format(Dev, "*DBG* ~tp got cast ~tp~n", + [Name, Cast]); + _ -> + io:format(Dev, "*DBG* ~tp got ~tp~n", [Name, Msg]) + end; print_event(Dev, {out, Msg, {To, _Tag}, State}, Name) -> - io:format(Dev, "*DBG* ~tp sent ~tp to ~tw, new state ~tp~n", - [Name, Msg, To, State]); + io:format(Dev, "*DBG* ~tp sent ~tp to ~tw, new state ~tp~n", + [Name, Msg, To, State]); print_event(Dev, {noreply, State}, Name) -> - io:format(Dev, "*DBG* ~tp new state ~tp~n", [Name, State]); + io:format(Dev, "*DBG* ~tp new state ~tp~n", [Name, State]); print_event(Dev, Event, Name) -> - io:format(Dev, "*DBG* ~tp dbg ~tp~n", [Name, Event]). \ No newline at end of file + io:format(Dev, "*DBG* ~tp dbg ~tp~n", [Name, Event]). \ No newline at end of file diff --git a/src/gen_emm.erl b/src/gen_emm.erl index 31ced81..9236938 100644 --- a/src/gen_emm.erl +++ b/src/gen_emm.erl @@ -4,6 +4,7 @@ -compile({inline_size, 128}). -include_lib("kernel/include/logger.hrl"). +-include("genGbh.hrl"). -import(maps, [iterator/1, next/1]). -import(gen_call, [gcall/3, gcall/4, greply/2, try_greply/2]). @@ -36,21 +37,11 @@ , wakeupFromHib/5 %% logger callback - , format_log/1, format_log/2 + , format_log/1, format_log/2, print_event/3 ]). -define(STACKTRACE(), element(2, erlang:process_info(self(), current_stacktrace))). -%% debug 调试相关宏定义 --define(NOT_DEBUG, []). --define(SYS_DEBUG(Debug, Name, Msg), - case Debug of - ?NOT_DEBUG -> - Debug; - _ -> - sys:handle_debug(Debug, fun print_event/3, Name, Msg) - end). - -type epmHandler() :: atom() | {atom(), term()}. @@ -95,6 +86,7 @@ {'logfile', string()}. -type startOpt() :: + daemon | {'timeout', timeout()} | {'debug', [debug_flag()]} | {'spawn_opt', [proc_lib:start_spawn_option()]} | @@ -218,6 +210,8 @@ init_it(Starter, Parent, ServerRef, _, _, Options) -> process_flag(trap_exit, true), Name = gen:name(ServerRef), Debug = gen:debug_options(Name, Options), + IsDaemon = lists:member(daemon, Options), + GbhOpts = #gbhOpts{daemon = IsDaemon}, HibernateAfterTimeout = gen:hibernate_after(Options), proc_lib:init_ack(Starter, {ok, self()}), receiveIng(Parent, Name, HibernateAfterTimeout, #{}, Debug, false). diff --git a/src/gen_ipc.erl b/src/gen_ipc.erl index e923782..0367c46 100644 --- a/src/gen_ipc.erl +++ b/src/gen_ipc.erl @@ -4,6 +4,7 @@ -compile({inline_size, 128}). -include_lib("kernel/include/logger.hrl"). +-include("genGbh.hrl"). -import(maps, [iterator/1, next/1]). -import(gen_call, [gcall/3, gcall/4, greply/2, try_greply/2]). @@ -46,6 +47,7 @@ , format_log/1 , format_log/2 , epm_log/1 + , print_event/3 ]). % 简写备注********************************** @@ -71,16 +73,6 @@ -define(CB_FORM_AFTER, 2). %% 从after 回调返回 -define(CB_FORM_EVENT, 3). %% 从event 回调返回 -%% debug 调试相关宏定义 --define(NOT_DEBUG, []). --define(SYS_DEBUG(Debug, Name, SystemEvent), - case Debug of - ?NOT_DEBUG -> - Debug; - _ -> - sys:handle_debug(Debug, fun print_event/3, Name, SystemEvent) - end). - %%%========================================================================== %%% Interface functions. %%%========================================================================== @@ -313,6 +305,7 @@ {'via', RegMod :: module(), ViaName :: term()}. -type startOpt() :: + daemon | {'timeout', Time :: timeout()} | {'spawn_opt', [proc_lib:spawn_option()]} | enterLoopOpt(). diff --git a/src/gen_mpp.erl b/src/gen_mpp.erl index 73110be..22b5d09 100644 --- a/src/gen_mpp.erl +++ b/src/gen_mpp.erl @@ -4,6 +4,7 @@ -compile({inline_size, 128}). -include_lib("kernel/include/logger.hrl"). +-include("genGbh.hrl"). -import(gen_call, [gcall/3, gcall/4, greply/2, try_greply/2]). @@ -35,22 +36,12 @@ , wakeupFromHib/8 %% logger callback - , format_log/1, format_log/2 + , format_log/1, format_log/2, print_event/3 ]). -define(STACKTRACE(), element(2, erlang:process_info(self(), current_stacktrace))). -%% debug 调试相关宏定义 --define(NOT_DEBUG, []). --define(SYS_DEBUG(Debug, Name, Msg), - case Debug of - ?NOT_DEBUG -> - Debug; - _ -> - sys:handle_debug(Debug, fun print_event/3, Name, Msg) - end). - -type serverName() :: {'local', atom()} | {'global', GlobalName :: term()} | @@ -64,6 +55,7 @@ | {'via', RegMod :: module(), ViaName :: term()}. -type startOpt() :: + daemon | {'timeout', Time :: timeout()} | {'spawn_opt', [proc_lib:spawn_option()]} | enterLoopOpt(). diff --git a/src/gen_srv.erl b/src/gen_srv.erl index 614a117..0a99374 100644 --- a/src/gen_srv.erl +++ b/src/gen_srv.erl @@ -4,6 +4,7 @@ -compile({inline_size, 128}). -include_lib("kernel/include/logger.hrl"). +-include("genGbh.hrl"). -import(gen_call, [gcall/3, gcall/4, greply/2, try_greply/2]). @@ -35,22 +36,12 @@ , wakeupFromHib/8 %% logger callback - , format_log/1, format_log/2 + , format_log/1, format_log/2, print_event/3 ]). -define(STACKTRACE(), element(2, erlang:process_info(self(), current_stacktrace))). -%% debug 调试相关宏定义 --define(NOT_DEBUG, []). --define(SYS_DEBUG(Debug, Name, Msg), - case Debug of - ?NOT_DEBUG -> - Debug; - _ -> - sys:handle_debug(Debug, fun print_event/3, Name, Msg) - end). - -type serverName() :: {'local', atom()} | {'global', GlobalName :: term()} | @@ -64,6 +55,7 @@ | {'via', RegMod :: module(), ViaName :: term()}. -type startOpt() :: + daemon | {'timeout', Time :: timeout()} | {'spawn_opt', [proc_lib:spawn_option()]} | enterLoopOpt().