From 46a295c5b9d66444f06f35e1fd2f3ac60787cf49 Mon Sep 17 00:00:00 2001 From: SisMaker <1713699517@qq.com> Date: Mon, 3 Jul 2023 01:03:59 +0800 Subject: [PATCH] =?UTF-8?q?ft:=20gen=5Fsrv.erl=20=E5=AE=88=E6=8A=A4?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=E6=B7=BB=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/gen_apu.erl | 2 +- src/gen_srv.erl | 232 +++++++++++++++++++++++++++++------------------- 2 files changed, 140 insertions(+), 94 deletions(-) diff --git a/src/gen_apu.erl b/src/gen_apu.erl index 46ac9ea..911929c 100644 --- a/src/gen_apu.erl +++ b/src/gen_apu.erl @@ -1042,7 +1042,7 @@ innerError(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, 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), + error_msg({handleError, {IClass, IReason, IStrace}}, Name, undefined, {Class, Reason, Stacktrace}, Module, Debug, CurState), kpS end; false -> diff --git a/src/gen_srv.erl b/src/gen_srv.erl index 2880aeb..3a4ab7a 100644 --- a/src/gen_srv.erl +++ b/src/gen_srv.erl @@ -33,7 +33,7 @@ , format_status/2 %% Internal callbacks - , wakeupFromHib/7 + , wakeupFromHib/8 %% logger callback , format_log/1, format_log/2, print_event/3 @@ -126,6 +126,12 @@ {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()} | @@ -203,15 +209,16 @@ 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), + 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, HibernateAfterTimeout, Debug, #{}, State, false); + receiveIng(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, #{}, State, false); {ok, State, Actions} -> proc_lib:init_ack(Starter, {ok, self()}), - loopEntry(Parent, Name, Module, HibernateAfterTimeout, Debug, #{}, State, listify(Actions)); + loopEntry(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, #{}, State, listify(Actions)); {stop, Reason} -> % 为了保持一致性,我们必须确保在 % %%父进程收到有关失败的通知之前,必须先注销%%注册名称(如果有)。 @@ -257,28 +264,29 @@ enter_loop(Module, State, Opts, ServerName, 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, HibernateAfterTimeout, Debug, #{}, State, listify(Actions)). + loopEntry(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, #{}, State, listify(Actions)). %%% Internal callbacks -wakeupFromHib(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState) -> +wakeupFromHib(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState) -> %% 这是一条新消息,唤醒了我们,因此我们必须立即收到它 - receiveIng(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, true). + receiveIng(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, true). -loopEntry(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, Actions) -> +loopEntry(Parent, Name, Module, GbhOpts, 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} -> + 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, HibernateAfterTimeout, NewDebug, NewTimers, CurState, listHib(IsHib), 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, HibernateAfterTimeout, NewDebug, NewTimers, CurState]); + proc_lib:hibernate(?MODULE, wakeupFromHib, [Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, NewTimers, CurState]); _ -> - receiveIng(Parent, Name, Module, HibernateAfterTimeout, NewDebug, NewTimers, CurState, false) + receiveIng(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, NewTimers, CurState, false) end end end. @@ -287,19 +295,19 @@ loopEntry(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, %%----------------------------------------------------------------- %% Callback functions for system messages handling. %%----------------------------------------------------------------- -system_continue(Parent, Debug, {Name, Module, HibernateAfterTimeout, Timers, CurState, IsHib}) -> +system_continue(Parent, Debug, {Name, Module, GbhOpts, HibernateAfterTimeout, Timers, CurState, IsHib}) -> case IsHib of true -> - proc_lib:hibernate(?MODULE, wakeupFromHib, [Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState]); + proc_lib:hibernate(?MODULE, wakeupFromHib, [Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState]); _ -> - receiveIng(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, false) + receiveIng(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, false) end. -spec system_terminate(_, _, _, [_]) -> no_return(). -system_terminate(Reason, _Parent, Debug, {Name, Module, _HibernateAfterTimeout, Timers, CurState, _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, HibernateAfterTimeout, Timers, CurState, IsHib}, _Module, OldVsn, Extra) -> +system_code_change({Name, Module, GbhOpts, HibernateAfterTimeout, Timers, CurState, IsHib}, _Module, OldVsn, Extra) -> case try Module:code_change(OldVsn, CurState, Extra) catch @@ -307,16 +315,16 @@ system_code_change({Name, Module, HibernateAfterTimeout, Timers, CurState, IsHib _C:_R:_S -> {_C, _R, _S} end of - {ok, NewState} -> {ok, {Name, Module, HibernateAfterTimeout, Timers, NewState, IsHib}}; + {ok, NewState} -> {ok, {Name, Module, GbhOpts, HibernateAfterTimeout, Timers, NewState, IsHib}}; Error -> Error end. -system_get_state({_Name, _Module, _HibernateAfterTimeout, _Timers, CurState, _IsHib}) -> +system_get_state({_Name, _Module, _GbhOpts, _HibernateAfterTimeout, _Timers, CurState, _IsHib}) -> {ok, CurState}. -system_replace_state(StateFun, {Name, Module, HibernateAfterTimeout, Timers, CurState, IsHib}) -> +system_replace_state(StateFun, {Name, Module, GbhOpts, HibernateAfterTimeout, Timers, CurState, IsHib}) -> NewState = StateFun(CurState), - {ok, NewState, {Name, Module, HibernateAfterTimeout, Timers, NewState, IsHib}}. + {ok, NewState, {Name, Module, GbhOpts, HibernateAfterTimeout, Timers, NewState, IsHib}}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% sys callbacks end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% API helpers start %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -694,68 +702,68 @@ start_monitor(Node, Name) when is_atom(Node), is_atom(Name) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% API helpers end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -receiveIng(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, IsHib) -> +receiveIng(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, IsHib) -> receive Msg -> case Msg of {'$gen_call', From, Request} -> - matchCallMsg(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, From, Request); + matchCallMsg(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, From, Request); {'$gen_cast', Cast} -> - matchCastMsg(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, Cast); + matchCastMsg(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Cast); {'$gen_clfn', From, MFA} -> - matchMFA(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, From, MFA, false); + matchMFA(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, From, MFA, false); {'$gen_clfs', From, MFA} -> - matchMFA(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, From, MFA, true); + matchMFA(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, From, MFA, true); {'$gen_csfn', MFA} -> - matchMFA(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, false, MFA, false); + matchMFA(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, false, MFA, false); {'$gen_csfs', MFA} -> - matchMFA(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, false, MFA, true); + 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, HibernateAfterTimeout, Debug, NewTimer, CurState, TimeoutMsg); + matchInfoMsg(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, NewTimer, CurState, TimeoutMsg); _ -> - matchInfoMsg(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, Msg) + 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, HibernateAfterTimeout, Timers, CurState, IsHib}, IsHib); + 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, HibernateAfterTimeout, 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, HibernateAfterTimeout, Debug, Timers, CurState]) + proc_lib:hibernate(?MODULE, wakeupFromHib, [Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState]) end. -matchCallMsg(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, From, Request) -> - NewDebug = ?SYS_DEBUG(Debug, Name, {in, {{call, From}, Request}}), +matchCallMsg(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, From, Request) -> + ?SYS_DEBUG(Debug, Name, {in, {{call, From}, Request}}), try Module:handleCall(Request, CurState, From) of Result -> - handleCR(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, CurState, Result, From, false) + handleCR(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Result, From, false) catch throw:Result -> - handleCR(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, CurState, Result, From, false); + handleCR(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Result, From, false); Class:Reason:Strace -> - terminate(Class, Reason, Strace, Name, Module, NewDebug, Timers, CurState, {{call, From}, Request}) + innerError(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, {{call, From}, Request}, Class, Reason, Strace) end. -matchCastMsg(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, Cast) -> - NewDebug = ?SYS_DEBUG(Debug, Name, {in, {cast, Cast}}), +matchCastMsg(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Cast) -> + ?SYS_DEBUG(Debug, Name, {in, {cast, Cast}}), try Module:handleCast(Cast, CurState) of Result -> - handleCR(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, CurState, Result, false, false) + handleCR(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Result, false, false) catch throw:Result -> - handleCR(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, CurState, Result, false, false); + handleCR(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Result, false, false); Class:Reason:Strace -> - terminate(Class, Reason, Strace, Name, Module, NewDebug, Timers, CurState, {cast, Cast}) + innerError(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, {cast, Cast}, Class, Reason, Strace) end. -matchMFA(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, From, MFA, IsWithState) -> - NewDebug = ?SYS_DEBUG(Debug, Name, {in, {mfa, MFA}}), +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 @@ -766,115 +774,116 @@ matchMFA(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, F end of Result -> - handleCR(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, CurState, Result, From, true) + handleCR(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Result, From, true) catch throw:Result -> - handleCR(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, CurState, Result, From, true); + handleCR(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Result, From, true); error:undef -> try_greply(From, {error, undef}), - receiveIng(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, CurState, false); + receiveIng(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, false); Class:Reason:Strace -> - terminate(Class, Reason, Strace, Name, Module, NewDebug, Timers, CurState, {mfa, MFA}) + try_greply(From, {error, {inner_error, {Class, Reason, Strace}}}), + innerError(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, {mfa, MFA}, Class, Reason, Strace) end. -matchInfoMsg(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, Msg) -> - NewDebug = ?SYS_DEBUG(Debug, Name, {in, {info, Msg}}), +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, HibernateAfterTimeout, NewDebug, Timers, CurState, Result, false, false) + handleCR(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Result, false, false) catch throw:Result -> - handleCR(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, CurState, Result, false, false); + handleCR(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Result, false, false); Class:Reason:Strace -> - terminate(Class, Reason, Strace, Name, Module, NewDebug, Timers, CurState, {info, Msg}) + innerError(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, {info, Msg}, Class, Reason, Strace) end. -doAfterCall(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, LeftAction, Args) -> - NewDebug = ?SYS_DEBUG(Debug, Name, {in, {doAfter, Args}}), +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, HibernateAfterTimeout, NewDebug, Timers, CurState, LeftAction, Result) + handleAR(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, LeftAction, Result) catch throw:Result -> - handleAR(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, CurState, LeftAction, Result); + handleAR(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, LeftAction, Result); Class:Reason:Strace -> - terminate(Class, Reason, Strace, Name, Module, NewDebug, Timers, CurState, {doAfter, Args}) + innerError(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, {doAfter, Args}, Class, Reason, Strace) end. -handleCR(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, Result, From, IsAnyRet) -> +handleCR(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, Result, From, IsAnyRet) -> case Result of kpS -> - receiveIng(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, false); + receiveIng(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, false); {reply, Reply} -> greply(From, Reply), - NewDebug = ?SYS_DEBUG(Debug, Name, {out, Reply, From, CurState}), - receiveIng(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, CurState, false); + ?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, HibernateAfterTimeout, Debug, Timers, CurState, false); + receiveIng(Parent, Name, Module, GbhOpts, 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) + ?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, HibernateAfterTimeout, Debug, Timers, NewState, false); + receiveIng(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, NewState, false); {reply, Reply, NewState} -> greply(From, Reply), - NewDebug = ?SYS_DEBUG(Debug, Name, {out, Reply, From, NewState}), - receiveIng(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, NewState, false); + ?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, HibernateAfterTimeout, Debug, Timers, NewState, false); + receiveIng(Parent, Name, Module, GbhOpts, 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) + ?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, HibernateAfterTimeout, Debug, Timers, NewState, listify(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} -> greply(From, Reply), - NewDebug = ?SYS_DEBUG(Debug, Name, {out, Reply, From, NewState}), - loopEntry(Parent, Name, Module, HibernateAfterTimeout, NewDebug, Timers, NewState, listify(Actions)); + ?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, HibernateAfterTimeout, Debug, Timers, NewState, listify(Actions)); + loopEntry(Parent, Name, Module, GbhOpts, 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)) + ?SYS_DEBUG(Debug, Name, {out, Reply, From, NewState}), + loopEntry(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, NewState, listify(Actions)) end; {stopReply, Reason, Reply, NewState} -> - NewDebug = ?SYS_DEBUG(Debug, Name, {out, Reply, From, NewState}), + ?SYS_DEBUG(Debug, Name, {out, Reply, From, NewState}), try - terminate(exit, Reason, ?STACKTRACE(), Name, Module, NewDebug, Timers, NewState, {return, stop_reply}) + terminate(exit, Reason, ?STACKTRACE(), Name, Module, Debug, Timers, NewState, {return, stop_reply}) after _ = greply(From, Reply) end; _AnyRet -> case IsAnyRet of true -> - receiveIng(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, false); + receiveIng(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, false); _ -> - terminate(exit, bad_ret, ?STACKTRACE(), Name, Module, Debug, Timers, CurState, {return, _AnyRet}) + innerError(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, {return, _AnyRet}, error, bad_ret, ?STACKTRACE()) end end. -handleAR(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, LeftAction, Result) -> +handleAR(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, LeftAction, Result) -> case Result of kpS -> - loopEntry(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, CurState, LeftAction); + loopEntry(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, CurState, LeftAction); {noreply, NewState} -> - loopEntry(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, NewState, LeftAction); + loopEntry(Parent, Name, Module, GbhOpts, HibernateAfterTimeout, Debug, Timers, NewState, LeftAction); {noreply, NewState, Actions} -> - loopEntry(Parent, Name, Module, HibernateAfterTimeout, Debug, Timers, NewState, listify(Actions) ++ LeftAction); + 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. @@ -895,9 +904,9 @@ doParseAL([OneAction | LeftActions], Name, Debug, IsHib, DoAfter, 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}}), + ?SYS_DEBUG(Debug, Name, {start_timer, {TimeoutName, Time, TimeoutMsg, Options}}), NewTimers = doRegisterTimer(TimeoutName, TimerRef, TimeoutMsg, Timers), - doParseAL(LeftActions, Name, NewDebug, IsHib, DoAfter, NewTimers) + doParseAL(LeftActions, Name, Debug, IsHib, DoAfter, NewTimers) end; {'nTimeout', TimeoutName, Time, TimeoutMsg} -> case Time of @@ -906,9 +915,9 @@ doParseAL([OneAction | LeftActions], Name, Debug, IsHib, DoAfter, 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, []}}), + ?SYS_DEBUG(Debug, Name, {start_timer, {TimeoutName, Time, TimeoutMsg, []}}), NewTimers = doRegisterTimer(TimeoutName, TimerRef, TimeoutMsg, Timers), - doParseAL(LeftActions, Name, NewDebug, IsHib, DoAfter, NewTimers) + doParseAL(LeftActions, Name, Debug, IsHib, DoAfter, NewTimers) end; {'uTimeout', TimeoutName, NewTimeoutMsg} -> NewTimers = doUpdateTimer(TimeoutName, NewTimeoutMsg, Timers), @@ -920,8 +929,8 @@ doParseAL([OneAction | LeftActions], Name, Debug, IsHib, DoAfter, Timers) -> 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); + ?SYS_DEBUG(Debug, Name, {start_timer, {timeout, Timeout, timeout, []}}), + doParseAL(LeftActions, Name, Debug, IsHib, DoAfter, Timers); _ -> {error, {bad_ActionType, OneAction}} end. @@ -993,7 +1002,28 @@ listHib(false) -> listHib(_) -> [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. @@ -1072,6 +1102,22 @@ error_info(Reason, Name, From, Msg, Module, Debug, State) -> }), ok. +error_msg(Reason, Name, From, Msg, Module, Debug, State) -> + Log = sys:get_log(Debug), + ?LOG_ERROR(#{label => {gen_srv, 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_srv:format_log/2, + error_logger => #{tag => error, report_cb => fun gen_srv:format_log/1} + }), + ok. + client_stacktrace(undefined) -> undefined; client_stacktrace({From, _Tag}) ->