.TH gen_server 3erl "stdlib 2.2" "Ericsson AB" "Erlang Module Definition" .SH NAME gen_server \- Generic Server Behaviour .SH DESCRIPTION .LP A behaviour module for implementing the server of a client-server relation\&. A generic server process (gen_server) implemented using this module will have a standard set of interface functions and include functionality for tracing and error reporting\&. It will also fit into an OTP supervision tree\&. Refer to \fBOTP Design Principles\fR\& for more information\&. .LP A gen_server assumes all specific parts to be located in a callback module exporting a pre-defined set of functions\&. The relationship between the behaviour functions and the callback functions can be illustrated as follows: .LP .nf gen_server module Callback module ----------------- --------------- gen_server:start_link -----> Module:init/1 gen_server:call gen_server:multi_call -----> Module:handle_call/3 gen_server:cast gen_server:abcast -----> Module:handle_cast/2 - -----> Module:handle_info/2 - -----> Module:terminate/2 - -----> Module:code_change/3 .fi .LP If a callback function fails or returns a bad value, the gen_server will terminate\&. .LP A gen_server handles system messages as documented in \fBsys(3erl)\fR\&\&. The \fIsys\fR\& module can be used for debugging a gen_server\&. .LP Note that a gen_server does not trap exit signals automatically, this must be explicitly initiated in the callback module\&. .LP Unless otherwise stated, all functions in this module fail if the specified gen_server does not exist or if bad arguments are given\&. .LP The gen_server process can go into hibernation (see \fBerlang(3erl)\fR\&) if a callback function specifies \fI\&'hibernate\&'\fR\& instead of a timeout value\&. This might be useful if the server is expected to be idle for a long time\&. However this feature should be used with care as hibernation implies at least two garbage collections (when hibernating and shortly after waking up) and is not something you\&'d want to do between each call to a busy server\&. .SH EXPORTS .LP .B start_link(Module, Args, Options) -> Result .br .B start_link(ServerName, Module, Args, Options) -> Result .br .RS .LP Types: .RS 3 ServerName = {local,Name} | {global,GlobalName} | {via,Module,ViaName} .br Name = atom() .br GlobalName = ViaName = term() .br Module = atom() .br Args = term() .br Options = [Option] .br Option = {debug,Dbgs} | {timeout,Time} | {spawn_opt,SOpts} .br Dbgs = [Dbg] .br Dbg = trace | log | statistics | {log_to_file,FileName} | {install,{Func,FuncState}} .br SOpts = [term()] .br Result = {ok,Pid} | ignore | {error,Error} .br Pid = pid() .br Error = {already_started,Pid} | term() .br .RE .RE .RS .LP Creates a gen_server process as part of a supervision tree\&. The function should be called, directly or indirectly, by the supervisor\&. It will, among other things, ensure that the gen_server is linked to the supervisor\&. .LP The gen_server process calls \fIModule:init/1\fR\& to initialize\&. To ensure a synchronized start-up procedure, \fIstart_link/3,4\fR\& does not return until \fIModule:init/1\fR\& has returned\&. .LP If \fIServerName={local,Name}\fR\& the gen_server is registered locally as \fIName\fR\& using \fIregister/2\fR\&\&. If \fIServerName={global,GlobalName}\fR\& the gen_server is registered globally as \fIGlobalName\fR\& using \fIglobal:register_name/2\fR\&\&. If no name is provided, the gen_server is not registered\&. If \fIServerName={via,Module,ViaName}\fR\&, the gen_server will register with the registry represented by \fIModule\fR\&\&. The \fIModule\fR\& callback should export the functions \fIregister_name/2\fR\&, \fIunregister_name/1\fR\&, \fIwhereis_name/1\fR\& and \fIsend/2\fR\&, which should behave like the corresponding functions in \fIglobal\fR\&\&. Thus, \fI{via,global,GlobalName}\fR\& is a valid reference\&. .LP \fIModule\fR\& is the name of the callback module\&. .LP \fIArgs\fR\& is an arbitrary term which is passed as the argument to \fIModule:init/1\fR\&\&. .LP If the option \fI{timeout,Time}\fR\& is present, the gen_server is allowed to spend \fITime\fR\& milliseconds initializing or it will be terminated and the start function will return \fI{error,timeout}\fR\&\&. .LP If the option \fI{debug,Dbgs}\fR\& is present, the corresponding \fIsys\fR\& function will be called for each item in \fIDbgs\fR\&\&. See \fBsys(3erl)\fR\&\&. .LP If the option \fI{spawn_opt,SOpts}\fR\& is present, \fISOpts\fR\& will be passed as option list to the \fIspawn_opt\fR\& BIF which is used to spawn the gen_server\&. See \fBerlang(3erl)\fR\&\&. .LP .RS -4 .B Note: .RE Using the spawn option \fImonitor\fR\& is currently not allowed, but will cause the function to fail with reason \fIbadarg\fR\&\&. .LP If the gen_server is successfully created and initialized the function returns \fI{ok,Pid}\fR\&, where \fIPid\fR\& is the pid of the gen_server\&. If there already exists a process with the specified \fIServerName\fR\& the function returns \fI{error,{already_started,Pid}}\fR\&, where \fIPid\fR\& is the pid of that process\&. .LP If \fIModule:init/1\fR\& fails with \fIReason\fR\&, the function returns \fI{error,Reason}\fR\&\&. If \fIModule:init/1\fR\& returns \fI{stop,Reason}\fR\& or \fIignore\fR\&, the process is terminated and the function returns \fI{error,Reason}\fR\& or \fIignore\fR\&, respectively\&. .RE .LP .B start(Module, Args, Options) -> Result .br .B start(ServerName, Module, Args, Options) -> Result .br .RS .LP Types: .RS 3 ServerName = {local,Name} | {global,GlobalName} | {via,Module,ViaName} .br Name = atom() .br GlobalName = ViaName = term() .br Module = atom() .br Args = term() .br Options = [Option] .br Option = {debug,Dbgs} | {timeout,Time} | {spawn_opt,SOpts} .br Dbgs = [Dbg] .br Dbg = trace | log | statistics | {log_to_file,FileName} | {install,{Func,FuncState}} .br SOpts = [term()] .br Result = {ok,Pid} | ignore | {error,Error} .br Pid = pid() .br Error = {already_started,Pid} | term() .br .RE .RE .RS .LP Creates a stand-alone gen_server process, i\&.e\&. a gen_server which is not part of a supervision tree and thus has no supervisor\&. .LP See \fBstart_link/3,4\fR\& for a description of arguments and return values\&. .RE .LP .B call(ServerRef, Request) -> Reply .br .B call(ServerRef, Request, Timeout) -> Reply .br .RS .LP Types: .RS 3 ServerRef = Name | {Name,Node} | {global,GlobalName} | {via,Module,ViaName} | pid() .br Node = atom() .br GlobalName = ViaName = term() .br Request = term() .br Timeout = int()>0 | infinity .br Reply = term() .br .RE .RE .RS .LP Makes a synchronous call to the gen_server \fIServerRef\fR\& by sending a request and waiting until a reply arrives or a timeout occurs\&. The gen_server will call \fIModule:handle_call/3\fR\& to handle the request\&. .LP \fIServerRef\fR\& can be: .RS 2 .TP 2 * the pid, .LP .TP 2 * \fIName\fR\&, if the gen_server is locally registered, .LP .TP 2 * \fI{Name,Node}\fR\&, if the gen_server is locally registered at another node, or .LP .TP 2 * \fI{global,GlobalName}\fR\&, if the gen_server is globally registered\&. .LP .TP 2 * \fI{via,Module,ViaName}\fR\&, if the gen_server is registered through an alternative process registry\&. .LP .RE .LP \fIRequest\fR\& is an arbitrary term which is passed as one of the arguments to \fIModule:handle_call/3\fR\&\&. .LP \fITimeout\fR\& is an integer greater than zero which specifies how many milliseconds to wait for a reply, or the atom \fIinfinity\fR\& to wait indefinitely\&. Default value is 5000\&. If no reply is received within the specified time, the function call fails\&. If the caller catches the failure and continues running, and the server is just late with the reply, it may arrive at any time later into the caller\&'s message queue\&. The caller must in this case be prepared for this and discard any such garbage messages that are two element tuples with a reference as the first element\&. .LP The return value \fIReply\fR\& is defined in the return value of \fIModule:handle_call/3\fR\&\&. .LP The call may fail for several reasons, including timeout and the called gen_server dying before or during the call\&. .LP The ancient behaviour of sometimes consuming the server exit message if the server died during the call while linked to the client has been removed in OTP R12B/Erlang 5\&.6\&. .RE .LP .B multi_call(Name, Request) -> Result .br .B multi_call(Nodes, Name, Request) -> Result .br .B multi_call(Nodes, Name, Request, Timeout) -> Result .br .RS .LP Types: .RS 3 Nodes = [Node] .br Node = atom() .br Name = atom() .br Request = term() .br Timeout = int()>=0 | infinity .br Result = {Replies,BadNodes} .br Replies = [{Node,Reply}] .br Reply = term() .br BadNodes = [Node] .br .RE .RE .RS .LP Makes a synchronous call to all gen_servers locally registered as \fIName\fR\& at the specified nodes by first sending a request to every node and then waiting for the replies\&. The gen_servers will call \fIModule:handle_call/3\fR\& to handle the request\&. .LP The function returns a tuple \fI{Replies,BadNodes}\fR\& where \fIReplies\fR\& is a list of \fI{Node,Reply}\fR\& and \fIBadNodes\fR\& is a list of node that either did not exist, or where the gen_server \fIName\fR\& did not exist or did not reply\&. .LP \fINodes\fR\& is a list of node names to which the request should be sent\&. Default value is the list of all known nodes \fI[node()|nodes()]\fR\&\&. .LP \fIName\fR\& is the locally registered name of each gen_server\&. .LP \fIRequest\fR\& is an arbitrary term which is passed as one of the arguments to \fIModule:handle_call/3\fR\&\&. .LP \fITimeout\fR\& is an integer greater than zero which specifies how many milliseconds to wait for each reply, or the atom \fIinfinity\fR\& to wait indefinitely\&. Default value is \fIinfinity\fR\&\&. If no reply is received from a node within the specified time, the node is added to \fIBadNodes\fR\&\&. .LP When a reply \fIReply\fR\& is received from the gen_server at a node \fINode\fR\&, \fI{Node,Reply}\fR\& is added to \fIReplies\fR\&\&. \fIReply\fR\& is defined in the return value of \fIModule:handle_call/3\fR\&\&. .LP .RS -4 .B Warning: .RE If one of the nodes is not capable of process monitors, for example C or Java nodes, and the gen_server is not started when the requests are sent, but starts within 2 seconds, this function waits the whole \fITimeout\fR\&, which may be infinity\&. .LP This problem does not exist if all nodes are Erlang nodes\&. .LP To avoid that late answers (after the timeout) pollutes the caller\&'s message queue, a middleman process is used to do the actual calls\&. Late answers will then be discarded when they arrive to a terminated process\&. .RE .LP .B cast(ServerRef, Request) -> ok .br .RS .LP Types: .RS 3 ServerRef = Name | {Name,Node} | {global,GlobalName} | {via,Module,ViaName} | pid() .br Node = atom() .br GlobalName = ViaName = term() .br Request = term() .br .RE .RE .RS .LP Sends an asynchronous request to the gen_server \fIServerRef\fR\& and returns \fIok\fR\& immediately, ignoring if the destination node or gen_server does not exist\&. The gen_server will call \fIModule:handle_cast/2\fR\& to handle the request\&. .LP See \fBcall/2,3\fR\& for a description of \fIServerRef\fR\&\&. .LP \fIRequest\fR\& is an arbitrary term which is passed as one of the arguments to \fIModule:handle_cast/2\fR\&\&. .RE .LP .B abcast(Name, Request) -> abcast .br .B abcast(Nodes, Name, Request) -> abcast .br .RS .LP Types: .RS 3 Nodes = [Node] .br Node = atom() .br Name = atom() .br Request = term() .br .RE .RE .RS .LP Sends an asynchronous request to the gen_servers locally registered as \fIName\fR\& at the specified nodes\&. The function returns immediately and ignores nodes that do not exist, or where the gen_server \fIName\fR\& does not exist\&. The gen_servers will call \fIModule:handle_cast/2\fR\& to handle the request\&. .LP See \fBmulti_call/2,3,4\fR\& for a description of the arguments\&. .RE .LP .B reply(Client, Reply) -> Result .br .RS .LP Types: .RS 3 Client - see below .br Reply = term() .br Result = term() .br .RE .RE .RS .LP This function can be used by a gen_server to explicitly send a reply to a client that called \fIcall/2,3\fR\& or \fImulti_call/2,3,4\fR\&, when the reply cannot be defined in the return value of \fIModule:handle_call/3\fR\&\&. .LP \fIClient\fR\& must be the \fIFrom\fR\& argument provided to the callback function\&. \fIReply\fR\& is an arbitrary term, which will be given back to the client as the return value of \fIcall/2,3\fR\& or \fImulti_call/2,3,4\fR\&\&. .LP The return value \fIResult\fR\& is not further defined, and should always be ignored\&. .RE .LP .B enter_loop(Module, Options, State) .br .B enter_loop(Module, Options, State, ServerName) .br .B enter_loop(Module, Options, State, Timeout) .br .B enter_loop(Module, Options, State, ServerName, Timeout) .br .RS .LP Types: .RS 3 Module = atom() .br Options = [Option] .br Option = {debug,Dbgs} .br Dbgs = [Dbg] .br Dbg = trace | log | statistics .br | {log_to_file,FileName} | {install,{Func,FuncState}} .br State = term() .br ServerName = {local,Name} | {global,GlobalName} | {via,Module,ViaName} .br Name = atom() .br GlobalName = ViaName = term() .br Timeout = int() | infinity .br .RE .RE .RS .LP Makes an existing process into a gen_server\&. Does not return, instead the calling process will enter the gen_server receive loop and become a gen_server process\&. The process \fImust\fR\& have been started using one of the start functions in \fIproc_lib\fR\&, see \fBproc_lib(3erl)\fR\&\&. The user is responsible for any initialization of the process, including registering a name for it\&. .LP This function is useful when a more complex initialization procedure is needed than the gen_server behaviour provides\&. .LP \fIModule\fR\&, \fIOptions\fR\& and \fIServerName\fR\& have the same meanings as when calling \fBgen_server:start[_link]/3,4\fR\&\&. However, if \fIServerName\fR\& is specified, the process must have been registered accordingly \fIbefore\fR\& this function is called\&. .LP \fIState\fR\& and \fITimeout\fR\& have the same meanings as in the return value of \fBModule:init/1\fR\&\&. Also, the callback module \fIModule\fR\& does not need to export an \fIinit/1\fR\& function\&. .LP Failure: If the calling process was not started by a \fIproc_lib\fR\& start function, or if it is not registered according to \fIServerName\fR\&\&. .RE .SH "CALLBACK FUNCTIONS" .LP The following functions should be exported from a \fIgen_server\fR\& callback module\&. .SH EXPORTS .LP .B Module:init(Args) -> Result .br .RS .LP Types: .RS 3 Args = term() .br Result = {ok,State} | {ok,State,Timeout} | {ok,State,hibernate} .br | {stop,Reason} | ignore .br State = term() .br Timeout = int()>=0 | infinity .br Reason = term() .br .RE .RE .RS .LP Whenever a gen_server is started using \fBgen_server:start/3,4\fR\& or \fBgen_server:start_link/3,4\fR\&, this function is called by the new process to initialize\&. .LP \fIArgs\fR\& is the \fIArgs\fR\& argument provided to the start function\&. .LP If the initialization is successful, the function should return \fI{ok,State}\fR\&, \fI{ok,State,Timeout}\fR\& or \fI{ok,State,hibernate}\fR\&, where \fIState\fR\& is the internal state of the gen_server\&. .LP If an integer timeout value is provided, a timeout will occur unless a request or a message is received within \fITimeout\fR\& milliseconds\&. A timeout is represented by the atom \fItimeout\fR\& which should be handled by the \fIhandle_info/2\fR\& callback function\&. The atom \fIinfinity\fR\& can be used to wait indefinitely, this is the default value\&. .LP If \fIhibernate\fR\& is specified instead of a timeout value, the process will go into hibernation when waiting for the next message to arrive (by calling \fBproc_lib:hibernate/3\fR\&)\&. .LP If something goes wrong during the initialization the function should return \fI{stop,Reason}\fR\& where \fIReason\fR\& is any term, or \fIignore\fR\&\&. .RE .LP .B Module:handle_call(Request, From, State) -> Result .br .RS .LP Types: .RS 3 Request = term() .br From = {pid(),Tag} .br State = term() .br Result = {reply,Reply,NewState} | {reply,Reply,NewState,Timeout} .br | {reply,Reply,NewState,hibernate} .br | {noreply,NewState} | {noreply,NewState,Timeout} .br | {noreply,NewState,hibernate} .br | {stop,Reason,Reply,NewState} | {stop,Reason,NewState} .br Reply = term() .br NewState = term() .br Timeout = int()>=0 | infinity .br Reason = term() .br .RE .RE .RS .LP Whenever a gen_server receives a request sent using \fBgen_server:call/2,3\fR\& or \fBgen_server:multi_call/2,3,4\fR\&, this function is called to handle the request\&. .LP \fIRequest\fR\& is the \fIRequest\fR\& argument provided to \fIcall\fR\& or \fImulti_call\fR\&\&. .LP \fIFrom\fR\& is a tuple \fI{Pid,Tag}\fR\& where \fIPid\fR\& is the pid of the client and \fITag\fR\& is a unique tag\&. .LP \fIState\fR\& is the internal state of the gen_server\&. .LP If the function returns \fI{reply,Reply,NewState}\fR\&, \fI{reply,Reply,NewState,Timeout}\fR\& or \fI{reply,Reply,NewState,hibernate}\fR\&, \fIReply\fR\& will be given back to \fIFrom\fR\& as the return value of \fIcall/2,3\fR\& or included in the return value of \fImulti_call/2,3,4\fR\&\&. The gen_server then continues executing with the possibly updated internal state \fINewState\fR\&\&. See \fIModule:init/1\fR\& for a description of \fITimeout\fR\& and \fIhibernate\fR\&\&. .LP If the functions returns \fI{noreply,NewState}\fR\&, \fI{noreply,NewState,Timeout}\fR\& or \fI{noreply,NewState,hibernate}\fR\&, the gen_server will continue executing with \fINewState\fR\&\&. Any reply to \fIFrom\fR\& must be given explicitly using \fBgen_server:reply/2\fR\&\&. .LP If the function returns \fI{stop,Reason,Reply,NewState}\fR\&, \fIReply\fR\& will be given back to \fIFrom\fR\&\&. If the function returns \fI{stop,Reason,NewState}\fR\&, any reply to \fIFrom\fR\& must be given explicitly using \fIgen_server:reply/2\fR\&\&. The gen_server will then call \fIModule:terminate(Reason,NewState)\fR\& and terminate\&. .RE .LP .B Module:handle_cast(Request, State) -> Result .br .RS .LP Types: .RS 3 Request = term() .br State = term() .br Result = {noreply,NewState} | {noreply,NewState,Timeout} .br | {noreply,NewState,hibernate} .br | {stop,Reason,NewState} .br NewState = term() .br Timeout = int()>=0 | infinity .br Reason = term() .br .RE .RE .RS .LP Whenever a gen_server receives a request sent using \fBgen_server:cast/2\fR\& or \fBgen_server:abcast/2,3\fR\&, this function is called to handle the request\&. .LP See \fIModule:handle_call/3\fR\& for a description of the arguments and possible return values\&. .RE .LP .B Module:handle_info(Info, State) -> Result .br .RS .LP Types: .RS 3 Info = timeout | term() .br State = term() .br Result = {noreply,NewState} | {noreply,NewState,Timeout} .br | {noreply,NewState,hibernate} .br | {stop,Reason,NewState} .br NewState = term() .br Timeout = int()>=0 | infinity .br Reason = normal | term() .br .RE .RE .RS .LP This function is called by a gen_server when a timeout occurs or when it receives any other message than a synchronous or asynchronous request (or a system message)\&. .LP \fIInfo\fR\& is either the atom \fItimeout\fR\&, if a timeout has occurred, or the received message\&. .LP See \fIModule:handle_call/3\fR\& for a description of the other arguments and possible return values\&. .RE .LP .B Module:terminate(Reason, State) .br .RS .LP Types: .RS 3 Reason = normal | shutdown | {shutdown,term()} | term() .br State = term() .br .RE .RE .RS .LP This function is called by a gen_server when it is about to terminate\&. It should be the opposite of \fIModule:init/1\fR\& and do any necessary cleaning up\&. When it returns, the gen_server terminates with \fIReason\fR\&\&. The return value is ignored\&. .LP \fIReason\fR\& is a term denoting the stop reason and \fIState\fR\& is the internal state of the gen_server\&. .LP \fIReason\fR\& depends on why the gen_server is terminating\&. If it is because another callback function has returned a stop tuple \fI{stop,\&.\&.}\fR\&, \fIReason\fR\& will have the value specified in that tuple\&. If it is due to a failure, \fIReason\fR\& is the error reason\&. .LP If the gen_server is part of a supervision tree and is ordered by its supervisor to terminate, this function will be called with \fIReason=shutdown\fR\& if the following conditions apply: .RS 2 .TP 2 * the gen_server has been set to trap exit signals, and .LP .TP 2 * the shutdown strategy as defined in the supervisor\&'s child specification is an integer timeout value, not \fIbrutal_kill\fR\&\&. .LP .RE .LP Even if the gen_server is \fInot\fR\& part of a supervision tree, this function will be called if it receives an \fI\&'EXIT\&'\fR\& message from its parent\&. \fIReason\fR\& will be the same as in the \fI\&'EXIT\&'\fR\& message\&. .LP Otherwise, the gen_server will be immediately terminated\&. .LP Note that for any other reason than \fInormal\fR\&, \fIshutdown\fR\&, or \fI{shutdown,Term}\fR\& the gen_server is assumed to terminate due to an error and an error report is issued using \fBerror_logger:format/2\fR\&\&. .RE .LP .B Module:code_change(OldVsn, State, Extra) -> {ok, NewState} | {error, Reason} .br .RS .LP Types: .RS 3 OldVsn = Vsn | {down, Vsn} .br Vsn = term() .br State = NewState = term() .br Extra = term() .br Reason = term() .br .RE .RE .RS .LP This function is called by a gen_server when it should update its internal state during a release upgrade/downgrade, i\&.e\&. when the instruction \fI{update,Module,Change,\&.\&.\&.}\fR\& where \fIChange={advanced,Extra}\fR\& is given in the \fIappup\fR\& file\&. See \fBOTP Design Principles\fR\& for more information\&. .LP In the case of an upgrade, \fIOldVsn\fR\& is \fIVsn\fR\&, and in the case of a downgrade, \fIOldVsn\fR\& is \fI{down,Vsn}\fR\&\&. \fIVsn\fR\& is defined by the \fIvsn\fR\& attribute(s) of the old version of the callback module \fIModule\fR\&\&. If no such attribute is defined, the version is the checksum of the BEAM file\&. .LP \fIState\fR\& is the internal state of the gen_server\&. .LP \fIExtra\fR\& is passed as-is from the \fI{advanced,Extra}\fR\& part of the update instruction\&. .LP If successful, the function shall return the updated internal state\&. .LP If the function returns \fI{error,Reason}\fR\&, the ongoing upgrade will fail and roll back to the old release\&. .RE .LP .B Module:format_status(Opt, [PDict, State]) -> Status .br .RS .LP Types: .RS 3 Opt = normal | terminate .br PDict = [{Key, Value}] .br State = term() .br Status = term() .br .RE .RE .RS .LP .RS -4 .B Note: .RE This callback is optional, so callback modules need not export it\&. The gen_server module provides a default implementation of this function that returns the callback module state\&. .LP This function is called by a gen_server process when: .RS 2 .TP 2 * One of \fBsys:get_status/1,2\fR\& is invoked to get the gen_server status\&. \fIOpt\fR\& is set to the atom \fInormal\fR\& for this case\&. .LP .TP 2 * The gen_server terminates abnormally and logs an error\&. \fIOpt\fR\& is set to the atom \fIterminate\fR\& for this case\&. .LP .RE .LP This function is useful for customising the form and appearance of the gen_server status for these cases\&. A callback module wishing to customise the \fIsys:get_status/1,2\fR\& return value as well as how its status appears in termination error logs exports an instance of \fIformat_status/2\fR\& that returns a term describing the current status of the gen_server\&. .LP \fIPDict\fR\& is the current value of the gen_server\&'s process dictionary\&. .LP \fIState\fR\& is the internal state of the gen_server\&. .LP The function should return \fIStatus\fR\&, a term that customises the details of the current state and status of the gen_server\&. There are no restrictions on the form \fIStatus\fR\& can take, but for the \fIsys:get_status/1,2\fR\& case (when \fIOpt\fR\& is \fInormal\fR\&), the recommended form for the \fIStatus\fR\& value is \fI[{data, [{"State", Term}]}]\fR\& where \fITerm\fR\& provides relevant details of the gen_server state\&. Following this recommendation isn\&'t required, but doing so will make the callback module status consistent with the rest of the \fIsys:get_status/1,2\fR\& return value\&. .LP One use for this function is to return compact alternative state representations to avoid having large state terms printed in logfiles\&. .RE .SH "SEE ALSO" .LP \fBgen_event(3erl)\fR\&, \fBgen_fsm(3erl)\fR\&, \fBsupervisor(3erl)\fR\&, \fBproc_lib(3erl)\fR\&, \fBsys(3erl)\fR\&