1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20-module(gen_server).
21
22%%%
23%%% NOTE: If init_ack() return values are modified, see comment
24%%%       above monitor_return() in gen.erl!
25%%%
26
27%%% ---------------------------------------------------
28%%%
29%%% The idea behind THIS server is that the user module
30%%% provides (different) functions to handle different
31%%% kind of inputs.
32%%% If the Parent process terminates the Module:terminate/2
33%%% function is called.
34%%%
35%%% The user module should export:
36%%%
37%%%   init(Args)
38%%%     ==> {ok, State}
39%%%         {ok, State, Timeout}
40%%%         ignore
41%%%         {stop, Reason}
42%%%
43%%%   handle_call(Msg, {From, Tag}, State)
44%%%
45%%%    ==> {reply, Reply, State}
46%%%        {reply, Reply, State, Timeout}
47%%%        {noreply, State}
48%%%        {noreply, State, Timeout}
49%%%        {stop, Reason, Reply, State}
50%%%              Reason = normal | shutdown | Term terminate(State) is called
51%%%
52%%%   handle_cast(Msg, State)
53%%%
54%%%    ==> {noreply, State}
55%%%        {noreply, State, Timeout}
56%%%        {stop, Reason, State}
57%%%              Reason = normal | shutdown | Term terminate(State) is called
58%%%
59%%%   handle_info(Info, State) Info is e.g. {'EXIT', P, R}, {nodedown, N}, ...
60%%%
61%%%    ==> {noreply, State}
62%%%        {noreply, State, Timeout}
63%%%        {stop, Reason, State}
64%%%              Reason = normal | shutdown | Term, terminate(State) is called
65%%%
66%%%   terminate(Reason, State) Let the user module clean up
67%%%        always called when server terminates
68%%%
69%%%    ==> ok
70%%%
71%%%
72%%% The work flow (of the server) can be described as follows:
73%%%
74%%%   User module                          Generic
75%%%   -----------                          -------
76%%%     start            ----->             start
77%%%     init             <-----              .
78%%%
79%%%                                         loop
80%%%     handle_call      <-----              .
81%%%                      ----->             reply
82%%%
83%%%     handle_cast      <-----              .
84%%%
85%%%     handle_info      <-----              .
86%%%
87%%%     terminate        <-----              .
88%%%
89%%%                      ----->             reply
90%%%
91%%%
92%%% ---------------------------------------------------
93
94%% API
95-export([start/3, start/4,
96	 start_link/3, start_link/4,
97         start_monitor/3, start_monitor/4,
98	 stop/1, stop/3,
99	 call/2, call/3,
100         send_request/2, wait_response/2,
101         receive_response/2, check_response/2,
102	 cast/2, reply/2,
103	 abcast/2, abcast/3,
104	 multi_call/2, multi_call/3, multi_call/4,
105	 enter_loop/3, enter_loop/4, enter_loop/5, wake_hib/6]).
106
107%% System exports
108-export([system_continue/3,
109	 system_terminate/4,
110	 system_code_change/4,
111	 system_get_state/1,
112	 system_replace_state/2,
113	 format_status/2]).
114
115%% logger callback
116-export([format_log/1, format_log/2]).
117
118%% Internal exports
119-export([init_it/6]).
120
121-include("logger.hrl").
122
123-define(
124   STACKTRACE(),
125   element(2, erlang:process_info(self(), current_stacktrace))).
126
127
128-type server_ref() ::
129        pid()
130      | (LocalName :: atom())
131      | {Name :: atom(), Node :: atom()}
132      | {'global', GlobalName :: term()}
133      | {'via', RegMod :: module(), ViaName :: term()}.
134
135-type request_id() :: term().
136
137%%%=========================================================================
138%%%  API
139%%%=========================================================================
140
141-callback init(Args :: term()) ->
142    {ok, State :: term()} | {ok, State :: term(), timeout() | hibernate | {continue, term()}} |
143    {stop, Reason :: term()} | ignore.
144-callback handle_call(Request :: term(), From :: {pid(), Tag :: term()},
145                      State :: term()) ->
146    {reply, Reply :: term(), NewState :: term()} |
147    {reply, Reply :: term(), NewState :: term(), timeout() | hibernate | {continue, term()}} |
148    {noreply, NewState :: term()} |
149    {noreply, NewState :: term(), timeout() | hibernate | {continue, term()}} |
150    {stop, Reason :: term(), Reply :: term(), NewState :: term()} |
151    {stop, Reason :: term(), NewState :: term()}.
152-callback handle_cast(Request :: term(), State :: term()) ->
153    {noreply, NewState :: term()} |
154    {noreply, NewState :: term(), timeout() | hibernate | {continue, term()}} |
155    {stop, Reason :: term(), NewState :: term()}.
156-callback handle_info(Info :: timeout | term(), State :: term()) ->
157    {noreply, NewState :: term()} |
158    {noreply, NewState :: term(), timeout() | hibernate | {continue, term()}} |
159    {stop, Reason :: term(), NewState :: term()}.
160-callback handle_continue(Info :: term(), State :: term()) ->
161    {noreply, NewState :: term()} |
162    {noreply, NewState :: term(), timeout() | hibernate | {continue, term()}} |
163    {stop, Reason :: term(), NewState :: term()}.
164-callback terminate(Reason :: (normal | shutdown | {shutdown, term()} |
165                               term()),
166                    State :: term()) ->
167    term().
168-callback code_change(OldVsn :: (term() | {down, term()}), State :: term(),
169                      Extra :: term()) ->
170    {ok, NewState :: term()} | {error, Reason :: term()}.
171-callback format_status(Opt, StatusData) -> Status when
172      Opt :: 'normal' | 'terminate',
173      StatusData :: [PDict | State],
174      PDict :: [{Key :: term(), Value :: term()}],
175      State :: term(),
176      Status :: term().
177
178-optional_callbacks(
179    [handle_info/2, handle_continue/2, terminate/2, code_change/3, format_status/2]).
180
181%%%  -----------------------------------------------------------------
182%%% Starts a generic server.
183%%% start(Mod, Args, Options)
184%%% start(Name, Mod, Args, Options)
185%%% start_link(Mod, Args, Options)
186%%% start_link(Name, Mod, Args, Options) where:
187%%%    Name ::= {local, atom()} | {global, term()} | {via, atom(), term()}
188%%%    Mod  ::= atom(), callback module implementing the 'real' server
189%%%    Args ::= term(), init arguments (to Mod:init/1)
190%%%    Options ::= [{timeout, Timeout} | {debug, [Flag]}]
191%%%      Flag ::= trace | log | {logfile, File} | statistics | debug
192%%%          (debug == log && statistics)
193%%% Returns: {ok, Pid} |
194%%%          {error, {already_started, Pid}} |
195%%%          {error, Reason}
196%%% -----------------------------------------------------------------
197start(Mod, Args, Options) ->
198    gen:start(?MODULE, nolink, Mod, Args, Options).
199
200start(Name, Mod, Args, Options) ->
201    gen:start(?MODULE, nolink, Name, Mod, Args, Options).
202
203start_link(Mod, Args, Options) ->
204    gen:start(?MODULE, link, Mod, Args, Options).
205
206start_link(Name, Mod, Args, Options) ->
207    gen:start(?MODULE, link, Name, Mod, Args, Options).
208
209start_monitor(Mod, Args, Options) ->
210    gen:start(?MODULE, monitor, Mod, Args, Options).
211
212start_monitor(Name, Mod, Args, Options) ->
213    gen:start(?MODULE, monitor, Name, Mod, Args, Options).
214
215
216%% -----------------------------------------------------------------
217%% Stop a generic server and wait for it to terminate.
218%% If the server is located at another node, that node will
219%% be monitored.
220%% -----------------------------------------------------------------
221stop(Name) ->
222    gen:stop(Name).
223
224stop(Name, Reason, Timeout) ->
225    gen:stop(Name, Reason, Timeout).
226
227%% -----------------------------------------------------------------
228%% Make a call to a generic server.
229%% If the server is located at another node, that node will
230%% be monitored.
231%% If the client is trapping exits and is linked server termination
232%% is handled here (? Shall we do that here (or rely on timeouts) ?).
233%% -----------------------------------------------------------------
234call(Name, Request) ->
235    case catch gen:call(Name, '$gen_call', Request) of
236	{ok,Res} ->
237	    Res;
238	{'EXIT',Reason} ->
239	    exit({Reason, {?MODULE, call, [Name, Request]}})
240    end.
241
242call(Name, Request, Timeout) ->
243    case catch gen:call(Name, '$gen_call', Request, Timeout) of
244	{ok,Res} ->
245	    Res;
246	{'EXIT',Reason} ->
247	    exit({Reason, {?MODULE, call, [Name, Request, Timeout]}})
248    end.
249
250%% -----------------------------------------------------------------
251%% Send a request to a generic server and return a Key which should be
252%% used with wait_response/2 or check_response/2 to fetch the
253%% result of the request.
254
255-spec send_request(Name::server_ref(), Request::term()) -> request_id().
256send_request(Name, Request) ->
257    gen:send_request(Name, '$gen_call', Request).
258
259-spec wait_response(RequestId::request_id(), timeout()) ->
260        {reply, Reply::term()} | 'timeout' | {error, {Reason::term(), server_ref()}}.
261wait_response(RequestId, Timeout) ->
262    gen:wait_response(RequestId, Timeout).
263
264-spec receive_response(RequestId::request_id(), timeout()) ->
265        {reply, Reply::term()} | 'timeout' | {error, {Reason::term(), server_ref()}}.
266receive_response(RequestId, Timeout) ->
267    gen:receive_response(RequestId, Timeout).
268
269-spec check_response(Msg::term(), RequestId::request_id()) ->
270        {reply, Reply::term()} | 'no_reply' | {error, {Reason::term(), server_ref()}}.
271check_response(Msg, RequestId) ->
272    gen:check_response(Msg, RequestId).
273
274%% -----------------------------------------------------------------
275%% Make a cast to a generic server.
276%% -----------------------------------------------------------------
277cast({global,Name}, Request) ->
278    catch global:send(Name, cast_msg(Request)),
279    ok;
280cast({via, Mod, Name}, Request) ->
281    catch Mod:send(Name, cast_msg(Request)),
282    ok;
283cast({Name,Node}=Dest, Request) when is_atom(Name), is_atom(Node) ->
284    do_cast(Dest, Request);
285cast(Dest, Request) when is_atom(Dest) ->
286    do_cast(Dest, Request);
287cast(Dest, Request) when is_pid(Dest) ->
288    do_cast(Dest, Request).
289
290do_cast(Dest, Request) ->
291    do_send(Dest, cast_msg(Request)),
292    ok.
293
294cast_msg(Request) -> {'$gen_cast',Request}.
295
296%% -----------------------------------------------------------------
297%% Send a reply to the client.
298%% -----------------------------------------------------------------
299reply(From, Reply) ->
300    gen:reply(From, Reply).
301
302%% -----------------------------------------------------------------
303%% Asynchronous broadcast, returns nothing, it's just send 'n' pray
304%%-----------------------------------------------------------------
305abcast(Name, Request) when is_atom(Name) ->
306    do_abcast([node() | nodes()], Name, cast_msg(Request)).
307
308abcast(Nodes, Name, Request) when is_list(Nodes), is_atom(Name) ->
309    do_abcast(Nodes, Name, cast_msg(Request)).
310
311do_abcast([Node|Nodes], Name, Msg) when is_atom(Node) ->
312    do_send({Name,Node},Msg),
313    do_abcast(Nodes, Name, Msg);
314do_abcast([], _,_) -> abcast.
315
316%%% -----------------------------------------------------------------
317%%% Make a call to servers at several nodes.
318%%% Returns: {[Replies],[BadNodes]}
319%%% A Timeout can be given
320%%%
321%%% A middleman process is used in case late answers arrives after
322%%% the timeout. If they would be allowed to glog the callers message
323%%% queue, it would probably become confused. Late answers will
324%%% now arrive to the terminated middleman and so be discarded.
325%%% -----------------------------------------------------------------
326multi_call(Name, Req)
327  when is_atom(Name) ->
328    do_multi_call([node() | nodes()], Name, Req, infinity).
329
330multi_call(Nodes, Name, Req)
331  when is_list(Nodes), is_atom(Name) ->
332    do_multi_call(Nodes, Name, Req, infinity).
333
334multi_call(Nodes, Name, Req, infinity) ->
335    do_multi_call(Nodes, Name, Req, infinity);
336multi_call(Nodes, Name, Req, Timeout)
337  when is_list(Nodes), is_atom(Name), is_integer(Timeout), Timeout >= 0 ->
338    do_multi_call(Nodes, Name, Req, Timeout).
339
340
341%%-----------------------------------------------------------------
342%% enter_loop(Mod, Options, State, <ServerName>, <TimeOut>) ->_
343%%
344%% Description: Makes an existing process into a gen_server.
345%%              The calling process will enter the gen_server receive
346%%              loop and become a gen_server process.
347%%              The process *must* have been started using one of the
348%%              start functions in proc_lib, see proc_lib(3).
349%%              The user is responsible for any initialization of the
350%%              process, including registering a name for it.
351%%-----------------------------------------------------------------
352enter_loop(Mod, Options, State) ->
353    enter_loop(Mod, Options, State, self(), infinity).
354
355enter_loop(Mod, Options, State, ServerName = {Scope, _})
356  when Scope == local; Scope == global ->
357    enter_loop(Mod, Options, State, ServerName, infinity);
358
359enter_loop(Mod, Options, State, ServerName = {via, _, _}) ->
360    enter_loop(Mod, Options, State, ServerName, infinity);
361
362enter_loop(Mod, Options, State, Timeout) ->
363    enter_loop(Mod, Options, State, self(), Timeout).
364
365enter_loop(Mod, Options, State, ServerName, Timeout) ->
366    Name = gen:get_proc_name(ServerName),
367    Parent = gen:get_parent(),
368    Debug = gen:debug_options(Name, Options),
369    HibernateAfterTimeout = gen:hibernate_after(Options),
370    loop(Parent, Name, State, Mod, Timeout, HibernateAfterTimeout, Debug).
371
372%%%========================================================================
373%%% Gen-callback functions
374%%%========================================================================
375
376%%% ---------------------------------------------------
377%%% Initiate the new process.
378%%% Register the name using the Rfunc function
379%%% Calls the Mod:init/Args function.
380%%% Finally an acknowledge is sent to Parent and the main
381%%% loop is entered.
382%%% ---------------------------------------------------
383init_it(Starter, self, Name, Mod, Args, Options) ->
384    init_it(Starter, self(), Name, Mod, Args, Options);
385init_it(Starter, Parent, Name0, Mod, Args, Options) ->
386    Name = gen:name(Name0),
387    Debug = gen:debug_options(Name, Options),
388    HibernateAfterTimeout = gen:hibernate_after(Options),
389
390    case init_it(Mod, Args) of
391	{ok, {ok, State}} ->
392	    proc_lib:init_ack(Starter, {ok, self()}),
393	    loop(Parent, Name, State, Mod, infinity, HibernateAfterTimeout, Debug);
394	{ok, {ok, State, TimeoutHibernateOrContinue}} ->
395	    proc_lib:init_ack(Starter, {ok, self()}),
396	    loop(Parent, Name, State, Mod, TimeoutHibernateOrContinue,
397	         HibernateAfterTimeout, Debug);
398	{ok, {stop, Reason}} ->
399	    %% For consistency, we must make sure that the
400	    %% registered name (if any) is unregistered before
401	    %% the parent process is notified about the failure.
402	    %% (Otherwise, the parent process could get
403	    %% an 'already_started' error if it immediately
404	    %% tried starting the process again.)
405	    gen:unregister_name(Name0),
406	    proc_lib:init_ack(Starter, {error, Reason}),
407	    exit(Reason);
408	{ok, ignore} ->
409	    gen:unregister_name(Name0),
410	    proc_lib:init_ack(Starter, ignore),
411	    exit(normal);
412	{ok, Else} ->
413	    Error = {bad_return_value, Else},
414	    proc_lib:init_ack(Starter, {error, Error}),
415	    exit(Error);
416	{'EXIT', Class, Reason, Stacktrace} ->
417	    gen:unregister_name(Name0),
418	    proc_lib:init_ack(Starter, {error, terminate_reason(Class, Reason, Stacktrace)}),
419	    erlang:raise(Class, Reason, Stacktrace)
420    end.
421init_it(Mod, Args) ->
422    try
423	{ok, Mod:init(Args)}
424    catch
425	throw:R -> {ok, R};
426	Class:R:S -> {'EXIT', Class, R, S}
427    end.
428
429%%%========================================================================
430%%% Internal functions
431%%%========================================================================
432%%% ---------------------------------------------------
433%%% The MAIN loop.
434%%% ---------------------------------------------------
435
436loop(Parent, Name, State, Mod, {continue, Continue} = Msg, HibernateAfterTimeout, Debug) ->
437    Reply = try_dispatch(Mod, handle_continue, Continue, State),
438    case Debug of
439	[] ->
440	    handle_common_reply(Reply, Parent, Name, undefined, Msg, Mod,
441				HibernateAfterTimeout, State);
442	_ ->
443	    Debug1 = sys:handle_debug(Debug, fun print_event/3, Name, Msg),
444	    handle_common_reply(Reply, Parent, Name, undefined, Msg, Mod,
445				HibernateAfterTimeout, State, Debug1)
446    end;
447
448loop(Parent, Name, State, Mod, hibernate, HibernateAfterTimeout, Debug) ->
449    proc_lib:hibernate(?MODULE,wake_hib,[Parent, Name, State, Mod, HibernateAfterTimeout, Debug]);
450
451loop(Parent, Name, State, Mod, infinity, HibernateAfterTimeout, Debug) ->
452	receive
453		Msg ->
454			decode_msg(Msg, Parent, Name, State, Mod, infinity, HibernateAfterTimeout, Debug, false)
455	after HibernateAfterTimeout ->
456		loop(Parent, Name, State, Mod, hibernate, HibernateAfterTimeout, Debug)
457	end;
458
459loop(Parent, Name, State, Mod, Time, HibernateAfterTimeout, Debug) ->
460    Msg = receive
461	      Input ->
462		    Input
463	  after Time ->
464		  timeout
465	  end,
466    decode_msg(Msg, Parent, Name, State, Mod, Time, HibernateAfterTimeout, Debug, false).
467
468wake_hib(Parent, Name, State, Mod, HibernateAfterTimeout, Debug) ->
469    Msg = receive
470	      Input ->
471		  Input
472	  end,
473    decode_msg(Msg, Parent, Name, State, Mod, hibernate, HibernateAfterTimeout, Debug, true).
474
475decode_msg(Msg, Parent, Name, State, Mod, Time, HibernateAfterTimeout, Debug, Hib) ->
476    case Msg of
477	{system, From, Req} ->
478	    sys:handle_system_msg(Req, From, Parent, ?MODULE, Debug,
479				  [Name, State, Mod, Time, HibernateAfterTimeout], Hib);
480	{'EXIT', Parent, Reason} ->
481	    terminate(Reason, ?STACKTRACE(), Name, undefined, Msg, Mod, State, Debug);
482	_Msg when Debug =:= [] ->
483	    handle_msg(Msg, Parent, Name, State, Mod, HibernateAfterTimeout);
484	_Msg ->
485	    Debug1 = sys:handle_debug(Debug, fun print_event/3,
486				      Name, {in, Msg}),
487	    handle_msg(Msg, Parent, Name, State, Mod, HibernateAfterTimeout, Debug1)
488    end.
489
490%%% ---------------------------------------------------
491%%% Send/receive functions
492%%% ---------------------------------------------------
493do_send(Dest, Msg) ->
494    try erlang:send(Dest, Msg)
495    catch
496        error:_ -> ok
497    end,
498    ok.
499
500do_multi_call([Node], Name, Req, infinity) when Node =:= node() ->
501    % Special case when multi_call is used with local node only.
502    % In that case we can leverage the benefit of recv_mark optimisation
503    % existing in simple gen:call.
504    try gen:call(Name, '$gen_call', Req, infinity) of
505        {ok, Res} -> {[{Node, Res}],[]}
506    catch exit:_ ->
507        {[], [Node]}
508    end;
509do_multi_call(Nodes, Name, Req, infinity) ->
510    Tag = make_ref(),
511    Monitors = send_nodes(Nodes, Name, Tag, Req),
512    rec_nodes(Tag, Monitors, Name, undefined);
513do_multi_call(Nodes, Name, Req, Timeout) ->
514    Tag = make_ref(),
515    Caller = self(),
516    Receiver =
517	spawn(
518	  fun() ->
519		  %% Middleman process. Should be unsensitive to regular
520		  %% exit signals. The sychronization is needed in case
521		  %% the receiver would exit before the caller started
522		  %% the monitor.
523		  process_flag(trap_exit, true),
524		  Mref = erlang:monitor(process, Caller),
525		  receive
526		      {Caller,Tag} ->
527			  Monitors = send_nodes(Nodes, Name, Tag, Req),
528			  TimerId = erlang:start_timer(Timeout, self(), ok),
529			  Result = rec_nodes(Tag, Monitors, Name, TimerId),
530			  exit({self(),Tag,Result});
531		      {'DOWN',Mref,_,_,_} ->
532			  %% Caller died before sending us the go-ahead.
533			  %% Give up silently.
534			  exit(normal)
535		  end
536	  end),
537    Mref = erlang:monitor(process, Receiver),
538    Receiver ! {self(),Tag},
539    receive
540	{'DOWN',Mref,_,_,{Receiver,Tag,Result}} ->
541	    Result;
542	{'DOWN',Mref,_,_,Reason} ->
543	    %% The middleman code failed. Or someone did
544	    %% exit(_, kill) on the middleman process => Reason==killed
545	    exit(Reason)
546    end.
547
548send_nodes(Nodes, Name, Tag, Req) ->
549    send_nodes(Nodes, Name, Tag, Req, []).
550
551send_nodes([Node|Tail], Name, Tag, Req, Monitors)
552  when is_atom(Node) ->
553    Monitor = start_monitor(Node, Name),
554    %% Handle non-existing names in rec_nodes.
555    catch {Name, Node} ! {'$gen_call', {self(), {Tag, Node}}, Req},
556    send_nodes(Tail, Name, Tag, Req, [Monitor | Monitors]);
557send_nodes([_Node|Tail], Name, Tag, Req, Monitors) ->
558    %% Skip non-atom Node
559    send_nodes(Tail, Name, Tag, Req, Monitors);
560send_nodes([], _Name, _Tag, _Req, Monitors) ->
561    Monitors.
562
563%% Against old nodes:
564%% If no reply has been delivered within 2 secs. (per node) check that
565%% the server really exists and wait for ever for the answer.
566%%
567%% Against contemporary nodes:
568%% Wait for reply, server 'DOWN', or timeout from TimerId.
569
570rec_nodes(Tag, Nodes, Name, TimerId) ->
571    rec_nodes(Tag, Nodes, Name, [], [], 2000, TimerId).
572
573rec_nodes(Tag, [{N,R}|Tail], Name, Badnodes, Replies, Time, TimerId ) ->
574    receive
575	{'DOWN', R, _, _, _} ->
576	    rec_nodes(Tag, Tail, Name, [N|Badnodes], Replies, Time, TimerId);
577	{{Tag, N}, Reply} ->  %% Tag is bound !!!
578	    erlang:demonitor(R, [flush]),
579	    rec_nodes(Tag, Tail, Name, Badnodes,
580		      [{N,Reply}|Replies], Time, TimerId);
581	{timeout, TimerId, _} ->
582	    erlang:demonitor(R, [flush]),
583	    %% Collect all replies that already have arrived
584	    rec_nodes_rest(Tag, Tail, Name, [N|Badnodes], Replies)
585    end;
586rec_nodes(Tag, [N|Tail], Name, Badnodes, Replies, Time, TimerId) ->
587    %% R6 node
588    receive
589	{nodedown, N} ->
590	    monitor_node(N, false),
591	    rec_nodes(Tag, Tail, Name, [N|Badnodes], Replies, 2000, TimerId);
592	{{Tag, N}, Reply} ->  %% Tag is bound !!!
593	    receive {nodedown, N} -> ok after 0 -> ok end,
594	    monitor_node(N, false),
595	    rec_nodes(Tag, Tail, Name, Badnodes,
596		      [{N,Reply}|Replies], 2000, TimerId);
597	{timeout, TimerId, _} ->
598	    receive {nodedown, N} -> ok after 0 -> ok end,
599	    monitor_node(N, false),
600	    %% Collect all replies that already have arrived
601	    rec_nodes_rest(Tag, Tail, Name, [N | Badnodes], Replies)
602    after Time ->
603	    case rpc:call(N, erlang, whereis, [Name]) of
604		Pid when is_pid(Pid) -> % It exists try again.
605		    rec_nodes(Tag, [N|Tail], Name, Badnodes,
606			      Replies, infinity, TimerId);
607		_ -> % badnode
608		    receive {nodedown, N} -> ok after 0 -> ok end,
609		    monitor_node(N, false),
610		    rec_nodes(Tag, Tail, Name, [N|Badnodes],
611			      Replies, 2000, TimerId)
612	    end
613    end;
614rec_nodes(_, [], _, Badnodes, Replies, _, TimerId) ->
615    case catch erlang:cancel_timer(TimerId) of
616	false ->  % It has already sent it's message
617	    receive
618		{timeout, TimerId, _} -> ok
619	    after 0 ->
620		    ok
621	    end;
622	_ -> % Timer was cancelled, or TimerId was 'undefined'
623	    ok
624    end,
625    {Replies, Badnodes}.
626
627%% Collect all replies that already have arrived
628rec_nodes_rest(Tag, [{N,R}|Tail], Name, Badnodes, Replies) ->
629    receive
630	{'DOWN', R, _, _, _} ->
631	    rec_nodes_rest(Tag, Tail, Name, [N|Badnodes], Replies);
632	{{Tag, N}, Reply} -> %% Tag is bound !!!
633	    erlang:demonitor(R, [flush]),
634	    rec_nodes_rest(Tag, Tail, Name, Badnodes, [{N,Reply}|Replies])
635    after 0 ->
636	    erlang:demonitor(R, [flush]),
637	    rec_nodes_rest(Tag, Tail, Name, [N|Badnodes], Replies)
638    end;
639rec_nodes_rest(Tag, [N|Tail], Name, Badnodes, Replies) ->
640    %% R6 node
641    receive
642	{nodedown, N} ->
643	    monitor_node(N, false),
644	    rec_nodes_rest(Tag, Tail, Name, [N|Badnodes], Replies);
645	{{Tag, N}, Reply} ->  %% Tag is bound !!!
646	    receive {nodedown, N} -> ok after 0 -> ok end,
647	    monitor_node(N, false),
648	    rec_nodes_rest(Tag, Tail, Name, Badnodes, [{N,Reply}|Replies])
649    after 0 ->
650	    receive {nodedown, N} -> ok after 0 -> ok end,
651	    monitor_node(N, false),
652	    rec_nodes_rest(Tag, Tail, Name, [N|Badnodes], Replies)
653    end;
654rec_nodes_rest(_Tag, [], _Name, Badnodes, Replies) ->
655    {Replies, Badnodes}.
656
657
658%%% ---------------------------------------------------
659%%% Monitor functions
660%%% ---------------------------------------------------
661
662start_monitor(Node, Name) when is_atom(Node), is_atom(Name) ->
663    if node() =:= nonode@nohost, Node =/= nonode@nohost ->
664	    Ref = make_ref(),
665	    self() ! {'DOWN', Ref, process, {Name, Node}, noconnection},
666	    {Node, Ref};
667       true ->
668	    case catch erlang:monitor(process, {Name, Node}) of
669		{'EXIT', _} ->
670		    %% Remote node is R6
671		    monitor_node(Node, true),
672		    Node;
673		Ref when is_reference(Ref) ->
674		    {Node, Ref}
675	    end
676    end.
677
678%% ---------------------------------------------------
679%% Helper functions for try-catch of callbacks.
680%% Returns the return value of the callback, or
681%% {'EXIT', Class, Reason, Stack} (if an exception occurs)
682%%
683%% The Class, Reason and Stack are given to erlang:raise/3
684%% to make sure proc_lib receives the proper reasons and
685%% stacktraces.
686%% ---------------------------------------------------
687
688try_dispatch({'$gen_cast', Msg}, Mod, State) ->
689    try_dispatch(Mod, handle_cast, Msg, State);
690try_dispatch(Info, Mod, State) ->
691    try_dispatch(Mod, handle_info, Info, State).
692
693try_dispatch(Mod, Func, Msg, State) ->
694    try
695	{ok, Mod:Func(Msg, State)}
696    catch
697	throw:R ->
698	    {ok, R};
699        error:undef = R:Stacktrace when Func == handle_info ->
700            case erlang:function_exported(Mod, handle_info, 2) of
701                false ->
702                    ?LOG_WARNING(
703                       #{label=>{gen_server,no_handle_info},
704                         module=>Mod,
705                         message=>Msg},
706                       #{domain=>[otp],
707                         report_cb=>fun gen_server:format_log/2,
708                         error_logger=>
709                             #{tag=>warning_msg,
710                               report_cb=>fun gen_server:format_log/1}}),
711                    {ok, {noreply, State}};
712                true ->
713                    {'EXIT', error, R, Stacktrace}
714            end;
715	Class:R:Stacktrace ->
716	    {'EXIT', Class, R, Stacktrace}
717    end.
718
719try_handle_call(Mod, Msg, From, State) ->
720    try
721	{ok, Mod:handle_call(Msg, From, State)}
722    catch
723	throw:R ->
724	    {ok, R};
725	Class:R:Stacktrace ->
726	    {'EXIT', Class, R, Stacktrace}
727    end.
728
729try_terminate(Mod, Reason, State) ->
730    case erlang:function_exported(Mod, terminate, 2) of
731	true ->
732	    try
733		{ok, Mod:terminate(Reason, State)}
734	    catch
735		throw:R ->
736		    {ok, R};
737		Class:R:Stacktrace ->
738		    {'EXIT', Class, R, Stacktrace}
739	   end;
740	false ->
741	    {ok, ok}
742    end.
743
744
745%%% ---------------------------------------------------
746%%% Message handling functions
747%%% ---------------------------------------------------
748
749handle_msg({'$gen_call', From, Msg}, Parent, Name, State, Mod, HibernateAfterTimeout) ->
750    Result = try_handle_call(Mod, Msg, From, State),
751    case Result of
752	{ok, {reply, Reply, NState}} ->
753	    reply(From, Reply),
754	    loop(Parent, Name, NState, Mod, infinity, HibernateAfterTimeout, []);
755	{ok, {reply, Reply, NState, Time1}} ->
756	    reply(From, Reply),
757	    loop(Parent, Name, NState, Mod, Time1, HibernateAfterTimeout, []);
758	{ok, {noreply, NState}} ->
759	    loop(Parent, Name, NState, Mod, infinity, HibernateAfterTimeout, []);
760	{ok, {noreply, NState, Time1}} ->
761	    loop(Parent, Name, NState, Mod, Time1, HibernateAfterTimeout, []);
762	{ok, {stop, Reason, Reply, NState}} ->
763	    try
764		terminate(Reason, ?STACKTRACE(), Name, From, Msg, Mod, NState, [])
765	    after
766		reply(From, Reply)
767	    end;
768	Other -> handle_common_reply(Other, Parent, Name, From, Msg, Mod, HibernateAfterTimeout, State)
769    end;
770handle_msg(Msg, Parent, Name, State, Mod, HibernateAfterTimeout) ->
771    Reply = try_dispatch(Msg, Mod, State),
772    handle_common_reply(Reply, Parent, Name, undefined, Msg, Mod, HibernateAfterTimeout, State).
773
774handle_msg({'$gen_call', From, Msg}, Parent, Name, State, Mod, HibernateAfterTimeout, Debug) ->
775    Result = try_handle_call(Mod, Msg, From, State),
776    case Result of
777	{ok, {reply, Reply, NState}} ->
778	    Debug1 = reply(Name, From, Reply, NState, Debug),
779	    loop(Parent, Name, NState, Mod, infinity, HibernateAfterTimeout, Debug1);
780	{ok, {reply, Reply, NState, Time1}} ->
781	    Debug1 = reply(Name, From, Reply, NState, Debug),
782	    loop(Parent, Name, NState, Mod, Time1, HibernateAfterTimeout, Debug1);
783	{ok, {noreply, NState}} ->
784	    Debug1 = sys:handle_debug(Debug, fun print_event/3, Name,
785				      {noreply, NState}),
786	    loop(Parent, Name, NState, Mod, infinity, HibernateAfterTimeout, Debug1);
787	{ok, {noreply, NState, Time1}} ->
788	    Debug1 = sys:handle_debug(Debug, fun print_event/3, Name,
789				      {noreply, NState}),
790	    loop(Parent, Name, NState, Mod, Time1, HibernateAfterTimeout, Debug1);
791	{ok, {stop, Reason, Reply, NState}} ->
792	    try
793		terminate(Reason, ?STACKTRACE(), Name, From, Msg, Mod, NState, Debug)
794	    after
795		_ = reply(Name, From, Reply, NState, Debug)
796	    end;
797	Other ->
798	    handle_common_reply(Other, Parent, Name, From, Msg, Mod, HibernateAfterTimeout, State, Debug)
799    end;
800handle_msg(Msg, Parent, Name, State, Mod, HibernateAfterTimeout, Debug) ->
801    Reply = try_dispatch(Msg, Mod, State),
802    handle_common_reply(Reply, Parent, Name, undefined, Msg, Mod, HibernateAfterTimeout, State, Debug).
803
804handle_common_reply(Reply, Parent, Name, From, Msg, Mod, HibernateAfterTimeout, State) ->
805    case Reply of
806	{ok, {noreply, NState}} ->
807	    loop(Parent, Name, NState, Mod, infinity, HibernateAfterTimeout, []);
808	{ok, {noreply, NState, Time1}} ->
809	    loop(Parent, Name, NState, Mod, Time1, HibernateAfterTimeout, []);
810	{ok, {stop, Reason, NState}} ->
811	    terminate(Reason, ?STACKTRACE(), Name, From, Msg, Mod, NState, []);
812	{'EXIT', Class, Reason, Stacktrace} ->
813	    terminate(Class, Reason, Stacktrace, Name, From, Msg, Mod, State, []);
814	{ok, BadReply} ->
815	    terminate({bad_return_value, BadReply}, ?STACKTRACE(), Name, From, Msg, Mod, State, [])
816    end.
817
818handle_common_reply(Reply, Parent, Name, From, Msg, Mod, HibernateAfterTimeout, State, Debug) ->
819    case Reply of
820	{ok, {noreply, NState}} ->
821	    Debug1 = sys:handle_debug(Debug, fun print_event/3, Name,
822				      {noreply, NState}),
823	    loop(Parent, Name, NState, Mod, infinity, HibernateAfterTimeout, Debug1);
824	{ok, {noreply, NState, Time1}} ->
825	    Debug1 = sys:handle_debug(Debug, fun print_event/3, Name,
826				      {noreply, NState}),
827	    loop(Parent, Name, NState, Mod, Time1, HibernateAfterTimeout, Debug1);
828	{ok, {stop, Reason, NState}} ->
829	    terminate(Reason, ?STACKTRACE(), Name, From, Msg, Mod, NState, Debug);
830	{'EXIT', Class, Reason, Stacktrace} ->
831	    terminate(Class, Reason, Stacktrace, Name, From, Msg, Mod, State, Debug);
832	{ok, BadReply} ->
833	    terminate({bad_return_value, BadReply}, ?STACKTRACE(), Name, From, Msg, Mod, State, Debug)
834    end.
835
836reply(Name, From, Reply, State, Debug) ->
837    reply(From, Reply),
838    sys:handle_debug(Debug, fun print_event/3, Name,
839		     {out, Reply, From, State} ).
840
841
842%%-----------------------------------------------------------------
843%% Callback functions for system messages handling.
844%%-----------------------------------------------------------------
845system_continue(Parent, Debug, [Name, State, Mod, Time, HibernateAfterTimeout]) ->
846    loop(Parent, Name, State, Mod, Time, HibernateAfterTimeout, Debug).
847
848-spec system_terminate(_, _, _, [_]) -> no_return().
849
850system_terminate(Reason, _Parent, Debug, [Name, State, Mod, _Time, _HibernateAfterTimeout]) ->
851    terminate(Reason, ?STACKTRACE(), Name, undefined, [], Mod, State, Debug).
852
853system_code_change([Name, State, Mod, Time, HibernateAfterTimeout], _Module, OldVsn, Extra) ->
854    case catch Mod:code_change(OldVsn, State, Extra) of
855	{ok, NewState} -> {ok, [Name, NewState, Mod, Time, HibernateAfterTimeout]};
856	Else -> Else
857    end.
858
859system_get_state([_Name, State, _Mod, _Time, _HibernateAfterTimeout]) ->
860    {ok, State}.
861
862system_replace_state(StateFun, [Name, State, Mod, Time, HibernateAfterTimeout]) ->
863    NState = StateFun(State),
864    {ok, NState, [Name, NState, Mod, Time, HibernateAfterTimeout]}.
865
866%%-----------------------------------------------------------------
867%% Format debug messages.  Print them as the call-back module sees
868%% them, not as the real erlang messages.  Use trace for that.
869%%-----------------------------------------------------------------
870print_event(Dev, {in, Msg}, Name) ->
871    case Msg of
872	{'$gen_call', {From, _Tag}, Call} ->
873	    io:format(Dev, "*DBG* ~tp got call ~tp from ~tw~n",
874		      [Name, Call, From]);
875	{'$gen_cast', Cast} ->
876	    io:format(Dev, "*DBG* ~tp got cast ~tp~n",
877		      [Name, Cast]);
878	_ ->
879	    io:format(Dev, "*DBG* ~tp got ~tp~n", [Name, Msg])
880    end;
881print_event(Dev, {out, Msg, {To,_Tag}, State}, Name) ->
882    io:format(Dev, "*DBG* ~tp sent ~tp to ~tw, new state ~tp~n",
883	      [Name, Msg, To, State]);
884print_event(Dev, {noreply, State}, Name) ->
885    io:format(Dev, "*DBG* ~tp new state ~tp~n", [Name, State]);
886print_event(Dev, Event, Name) ->
887    io:format(Dev, "*DBG* ~tp dbg  ~tp~n", [Name, Event]).
888
889
890%%% ---------------------------------------------------
891%%% Terminate the server.
892%%%
893%%% terminate/8 is triggered by {stop, Reason} or bad
894%%% return values. The stacktrace is generated via the
895%%% ?STACKTRACE() macro and the ReportReason must not
896%%% be wrapped in tuples.
897%%%
898%%% terminate/9 is triggered in case of error/exit in
899%%% the user callback. In this case the report reason
900%%% always includes the user stacktrace.
901%%%
902%%% The reason received in the terminate/2 callbacks
903%%% always includes the stacktrace for errors and never
904%%% for exits.
905%%% ---------------------------------------------------
906
907-spec terminate(_, _, _, _, _, _, _, _) -> no_return().
908terminate(Reason, Stacktrace, Name, From, Msg, Mod, State, Debug) ->
909  terminate(exit, Reason, Stacktrace, Reason, Name, From, Msg, Mod, State, Debug).
910
911-spec terminate(_, _, _, _, _, _, _, _, _) -> no_return().
912terminate(Class, Reason, Stacktrace, Name, From, Msg, Mod, State, Debug) ->
913  ReportReason = {Reason, Stacktrace},
914  terminate(Class, Reason, Stacktrace, ReportReason, Name, From, Msg, Mod, State, Debug).
915
916-spec terminate(_, _, _, _, _, _, _, _, _, _) -> no_return().
917terminate(Class, Reason, Stacktrace, ReportReason, Name, From, Msg, Mod, State, Debug) ->
918    Reply = try_terminate(Mod, terminate_reason(Class, Reason, Stacktrace), State),
919    case Reply of
920	{'EXIT', C, R, S} ->
921	    error_info({R, S}, Name, From, Msg, Mod, State, Debug),
922	    erlang:raise(C, R, S);
923	_ ->
924	    case {Class, Reason} of
925		{exit, normal} -> ok;
926		{exit, shutdown} -> ok;
927		{exit, {shutdown,_}} -> ok;
928		_ ->
929		    error_info(ReportReason, Name, From, Msg, Mod, State, Debug)
930	    end
931    end,
932    case Stacktrace of
933	[] ->
934	    erlang:Class(Reason);
935	_ ->
936	    erlang:raise(Class, Reason, Stacktrace)
937    end.
938
939terminate_reason(error, Reason, Stacktrace) -> {Reason, Stacktrace};
940terminate_reason(exit, Reason, _Stacktrace) -> Reason.
941
942error_info(_Reason, application_controller, _From, _Msg, _Mod, _State, _Debug) ->
943    %% OTP-5811 Don't send an error report if it's the system process
944    %% application_controller which is terminating - let init take care
945    %% of it instead
946    ok;
947error_info(Reason, Name, From, Msg, Mod, State, Debug) ->
948    Log = sys:get_log(Debug),
949    ?LOG_ERROR(#{label=>{gen_server,terminate},
950                 name=>Name,
951                 last_message=>Msg,
952                 state=>format_status(terminate, Mod, get(), State),
953                 log=>format_log_state(Mod, Log),
954                 reason=>Reason,
955                 client_info=>client_stacktrace(From)},
956               #{domain=>[otp],
957                 report_cb=>fun gen_server:format_log/2,
958                 error_logger=>#{tag=>error,
959                                 report_cb=>fun gen_server:format_log/1}}),
960    ok.
961
962client_stacktrace(undefined) ->
963    undefined;
964client_stacktrace({From,_Tag}) ->
965    client_stacktrace(From);
966client_stacktrace(From) when is_pid(From), node(From) =:= node() ->
967    case process_info(From, [current_stacktrace, registered_name]) of
968        undefined ->
969            {From,dead};
970        [{current_stacktrace, Stacktrace}, {registered_name, []}]  ->
971            {From,{From,Stacktrace}};
972        [{current_stacktrace, Stacktrace}, {registered_name, Name}]  ->
973            {From,{Name,Stacktrace}}
974    end;
975client_stacktrace(From) when is_pid(From) ->
976    {From,remote}.
977
978
979%% format_log/1 is the report callback used by Logger handler
980%% error_logger only. It is kept for backwards compatibility with
981%% legacy error_logger event handlers. This function must always
982%% return {Format,Args} compatible with the arguments in this module's
983%% calls to error_logger prior to OTP-21.0.
984format_log(Report) ->
985    Depth = error_logger:get_format_depth(),
986    FormatOpts = #{chars_limit => unlimited,
987                   depth => Depth,
988                   single_line => false,
989                   encoding => utf8},
990    format_log_multi(limit_report(Report,Depth),FormatOpts).
991
992limit_report(Report,unlimited) ->
993    Report;
994limit_report(#{label:={gen_server,terminate},
995               last_message:=Msg,
996               state:=State,
997               log:=Log,
998               reason:=Reason,
999               client_info:=Client}=Report,
1000            Depth) ->
1001    Report#{last_message=>io_lib:limit_term(Msg,Depth),
1002            state=>io_lib:limit_term(State,Depth),
1003            log=>[io_lib:limit_term(L,Depth)||L<-Log],
1004            reason=>io_lib:limit_term(Reason,Depth),
1005            client_info=>limit_client_report(Client,Depth)};
1006limit_report(#{label:={gen_server,no_handle_info},
1007               message:=Msg}=Report,Depth) ->
1008    Report#{message=>io_lib:limit_term(Msg,Depth)}.
1009
1010limit_client_report({From,{Name,Stacktrace}},Depth) ->
1011    {From,{Name,io_lib:limit_term(Stacktrace,Depth)}};
1012limit_client_report(Client,_) ->
1013    Client.
1014
1015%% format_log/2 is the report callback for any Logger handler, except
1016%% error_logger.
1017format_log(Report, FormatOpts0) ->
1018    Default = #{chars_limit => unlimited,
1019                depth => unlimited,
1020                single_line => false,
1021                encoding => utf8},
1022    FormatOpts = maps:merge(Default,FormatOpts0),
1023    IoOpts =
1024        case FormatOpts of
1025            #{chars_limit:=unlimited} ->
1026                [];
1027            #{chars_limit:=Limit} ->
1028                [{chars_limit,Limit}]
1029        end,
1030    {Format,Args} = format_log_single(Report, FormatOpts),
1031    io_lib:format(Format, Args, IoOpts).
1032
1033format_log_single(#{label:={gen_server,terminate},
1034                    name:=Name,
1035                    last_message:=Msg,
1036                    state:=State,
1037                    log:=Log,
1038                    reason:=Reason,
1039                    client_info:=Client},
1040                  #{single_line:=true,depth:=Depth}=FormatOpts) ->
1041    P = p(FormatOpts),
1042    Format1 = lists:append(["Generic server ",P," terminating. Reason: ",P,
1043                            ". Last message: ", P, ". State: ",P,"."]),
1044    {ServerLogFormat,ServerLogArgs} = format_server_log_single(Log,FormatOpts),
1045    {ClientLogFormat,ClientLogArgs} = format_client_log_single(Client,FormatOpts),
1046
1047    Args1 =
1048        case Depth of
1049            unlimited ->
1050                [Name,fix_reason(Reason),Msg,State];
1051            _ ->
1052                [Name,Depth,fix_reason(Reason),Depth,Msg,Depth,State,Depth]
1053        end,
1054    {Format1++ServerLogFormat++ClientLogFormat,
1055     Args1++ServerLogArgs++ClientLogArgs};
1056format_log_single(#{label:={gen_server,no_handle_info},
1057                    module:=Mod,
1058                    message:=Msg},
1059                  #{single_line:=true,depth:=Depth}=FormatOpts) ->
1060    P = p(FormatOpts),
1061    Format = lists:append(["Undefined handle_info in ",P,
1062                           ". Unhandled message: ",P,"."]),
1063    Args =
1064        case Depth of
1065            unlimited ->
1066                [Mod,Msg];
1067            _ ->
1068                [Mod,Depth,Msg,Depth]
1069        end,
1070    {Format,Args};
1071format_log_single(Report,FormatOpts) ->
1072    format_log_multi(Report,FormatOpts).
1073
1074format_log_multi(#{label:={gen_server,terminate},
1075                   name:=Name,
1076                   last_message:=Msg,
1077                   state:=State,
1078                   log:=Log,
1079                   reason:=Reason,
1080                   client_info:=Client},
1081                 #{depth:=Depth}=FormatOpts) ->
1082    Reason1 = fix_reason(Reason),
1083    {ClientFmt,ClientArgs} = format_client_log(Client,FormatOpts),
1084    P = p(FormatOpts),
1085    Format =
1086        lists:append(
1087          ["** Generic server ",P," terminating \n"
1088           "** Last message in was ",P,"~n"
1089           "** When Server state == ",P,"~n"
1090           "** Reason for termination ==~n** ",P,"~n"] ++
1091               case Log of
1092                   [] -> [];
1093                   _ -> ["** Log ==~n** ["|
1094                         lists:join(",~n    ",lists:duplicate(length(Log),P))]++
1095                            ["]~n"]
1096               end) ++ ClientFmt,
1097    Args =
1098        case Depth of
1099            unlimited ->
1100                [Name, Msg, State, Reason1] ++ Log ++ ClientArgs;
1101            _ ->
1102                [Name, Depth, Msg, Depth, State, Depth, Reason1, Depth] ++
1103                    case Log of
1104                        [] -> [];
1105                        _ -> lists:flatmap(fun(L) -> [L, Depth] end, Log)
1106                    end ++ ClientArgs
1107        end,
1108    {Format,Args};
1109format_log_multi(#{label:={gen_server,no_handle_info},
1110                   module:=Mod,
1111                   message:=Msg},
1112                 #{depth:=Depth}=FormatOpts) ->
1113    P = p(FormatOpts),
1114    Format =
1115        "** Undefined handle_info in ~p~n"
1116        "** Unhandled message: "++P++"~n",
1117    Args =
1118        case Depth of
1119            unlimited ->
1120                [Mod,Msg];
1121            _ ->
1122                [Mod,Msg,Depth]
1123                    end,
1124    {Format,Args}.
1125
1126fix_reason({undef,[{M,F,A,L}|MFAs]}=Reason) ->
1127    case code:is_loaded(M) of
1128        false ->
1129            {'module could not be loaded',[{M,F,A,L}|MFAs]};
1130        _ ->
1131            case erlang:function_exported(M, F, length(A)) of
1132                true ->
1133                    Reason;
1134                false ->
1135                    {'function not exported',[{M,F,A,L}|MFAs]}
1136            end
1137    end;
1138fix_reason(Reason) ->
1139    Reason.
1140
1141format_server_log_single([],_) ->
1142    {"",[]};
1143format_server_log_single(Log,FormatOpts) ->
1144    Args =
1145        case maps:get(depth,FormatOpts) of
1146            unlimited ->
1147                [Log];
1148            Depth ->
1149                [Log, Depth]
1150        end,
1151     {" Log: "++p(FormatOpts),Args}.
1152
1153format_client_log_single(undefined,_) ->
1154    {"",[]};
1155format_client_log_single({From,dead},_) ->
1156    {" Client ~0p is dead.",[From]};
1157format_client_log_single({From,remote},_) ->
1158    {" Client ~0p is remote on node ~0p.", [From, node(From)]};
1159format_client_log_single({_From,{Name,Stacktrace0}},FormatOpts) ->
1160    P = p(FormatOpts),
1161    %% Minimize the stacktrace a bit for single line reports. This is
1162    %% hopefully enough to point out the position.
1163    Stacktrace = lists:sublist(Stacktrace0,4),
1164    Args =
1165        case maps:get(depth,FormatOpts) of
1166            unlimited ->
1167                [Name, Stacktrace];
1168            Depth ->
1169                [Name, Depth, Stacktrace, Depth]
1170        end,
1171    {" Client "++P++" stacktrace: "++P++".", Args}.
1172
1173format_client_log(undefined,_) ->
1174    {"", []};
1175format_client_log({From,dead},_) ->
1176    {"** Client ~p is dead~n", [From]};
1177format_client_log({From,remote},_) ->
1178    {"** Client ~p is remote on node ~p~n", [From, node(From)]};
1179format_client_log({_From,{Name,Stacktrace}},FormatOpts) ->
1180    P = p(FormatOpts),
1181    Format = lists:append(["** Client ",P," stacktrace~n",
1182                           "** ",P,"~n"]),
1183    Args =
1184        case maps:get(depth,FormatOpts) of
1185            unlimited ->
1186                [Name, Stacktrace];
1187            Depth ->
1188                [Name, Depth, Stacktrace, Depth]
1189        end,
1190    {Format,Args}.
1191
1192p(#{single_line:=Single,depth:=Depth,encoding:=Enc}) ->
1193    "~"++single(Single)++mod(Enc)++p(Depth);
1194p(unlimited) ->
1195    "p";
1196p(_Depth) ->
1197    "P".
1198
1199single(true) -> "0";
1200single(false) -> "".
1201
1202mod(latin1) -> "";
1203mod(_) -> "t".
1204
1205%%-----------------------------------------------------------------
1206%% Status information
1207%%-----------------------------------------------------------------
1208format_status(Opt, StatusData) ->
1209    [PDict, SysState, Parent, Debug, [Name, State, Mod, _Time, _HibernateAfterTimeout]] = StatusData,
1210    Header = gen:format_status_header("Status for generic server", Name),
1211    Log = sys:get_log(Debug),
1212    Specific = case format_status(Opt, Mod, PDict, State) of
1213		  S when is_list(S) -> S;
1214		  S -> [S]
1215	      end,
1216    [{header, Header},
1217     {data, [{"Status", SysState},
1218	     {"Parent", Parent},
1219	     {"Logged events", format_log_state(Mod, Log)}]} |
1220     Specific].
1221
1222format_log_state(Mod, Log) ->
1223    [case Event of
1224         {out,Msg,From,State} ->
1225             {out,Msg,From,format_status(terminate, Mod, get(), State)};
1226         {noreply,State} ->
1227             {noreply,format_status(terminate, Mod, get(), State)};
1228         _ -> Event
1229     end || Event <- Log].
1230
1231format_status(Opt, Mod, PDict, State) ->
1232    DefStatus = case Opt of
1233		    terminate -> State;
1234		    _ -> [{data, [{"State", State}]}]
1235		end,
1236    case erlang:function_exported(Mod, format_status, 2) of
1237	true ->
1238	    case catch Mod:format_status(Opt, [PDict, State]) of
1239		{'EXIT', _} -> DefStatus;
1240		Else -> Else
1241	    end;
1242	_ ->
1243	    DefStatus
1244    end.
1245