gen_server
Generic server behavior.
This behavior module provides the server of a client-server
relation. A generic server process (gen_server
) implemented using
this module has a standard set of interface functions and
includes functionality for tracing and error reporting. It also
fits into an OTP supervision tree. For more information, see section
gen_server Behaviour in OTP Design Principles.
A gen_server
process assumes all specific parts to be located in
a callback module exporting a predefined set of functions.
The relationship between the behavior functions and the callback
functions is as follows:
gen_server module Callback module ----------------- --------------- gen_server:start gen_server:start_link -----> Module:init/1 gen_server:stop -----> Module:terminate/2 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
If a callback function fails or returns a bad value, the
gen_server
process terminates.
A gen_server
process handles system messages as described in
sys(3)
. The sys
module
can be used for debugging a gen_server
process.
Notice that a gen_server
process does not trap exit signals
automatically, this must be explicitly initiated in the callback
module.
Unless otherwise stated, all functions in this module fail if
the specified gen_server
process does not exist or if bad
arguments are specified.
The gen_server
process can go into hibernation
(see
erlang:hibernate/3
) if a callback
function specifies 'hibernate'
instead of a time-out value. This
can be useful if the server is expected to be idle for a long
time. However, use this feature with care, as hibernation
implies at least two garbage collections (when hibernating and
shortly after waking up) and is not something you want to do
between each call to a busy server.
Functions
abcast(Name, Request) -> abcast
abcast(Nodes, Name, Request) -> abcast
Nodes = [Node]
Node = atom()
Name = atom()
Request = term()
Sends an asynchronous request to the gen_server
processes
locally registered as Name
at the specified nodes. The function
returns immediately and ignores nodes that do not exist, or
where the gen_server
Name
does not exist.
The gen_server
processes call
Module:handle_cast/2
to handle the request.
For a description of the arguments, see
multi_call/2,3,4
.
call(ServerRef, Request) -> Reply
call(ServerRef, Request, Timeout) -> Reply
ServerRef = Name | {Name,Node} | {global,GlobalName}
| {via,Module,ViaName} | pid()
Node = atom()
GlobalName = ViaName = term()
Request = term()
Timeout = int()>0 | infinity
Reply = term()
Makes a synchronous call to the ServerRef
of the
gen_server
process
by sending a request and waiting until a reply arrives or a
time-out occurs. The gen_server
process calls
Module:handle_call/3
to handle the request.
ServerRef
can be any of the following:
- The pid
Name
, if thegen_server
process is locally registered{Name,Node}
, if thegen_server
process is locally registered at another node{global,GlobalName}
, if thegen_server
process is globally registered{via,Module,ViaName}
, if thegen_server
process is registered through an alternative process registry
Request
is any term that is passed as one of
the arguments to Module:handle_call/3
.
Timeout
is an integer greater than zero that
specifies how many milliseconds to wait for a reply, or
the atom infinity
to wait indefinitely. Defaults to
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 can arrive at any time later into the message queue of the caller.
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.
The return value Reply
is defined in the return value
of Module:handle_call/3
.
The call can fail for many reasons, including time-out and the
called gen_server
process dying before or during the call.
Note!
The ancient behavior of sometimes consuming the server exit message if the server died during the call while linked to the client was removed in Erlang 5.6/OTP R12B.
cast(ServerRef, Request) -> ok
ServerRef = Name | {Name,Node} | {global,GlobalName}
| {via,Module,ViaName} | pid()
Node = atom()
GlobalName = ViaName = term()
Request = term()
Sends an asynchronous request to the ServerRef
of the
gen_server
process
and returns ok
immediately, ignoring
if the destination node or gen_server
process does not exist.
The gen_server
process calls
Module:handle_cast/2
to handle the request.
For a description of ServerRef
, see
call/2,3
.
Request
is any term that is passed as one
of the arguments to Module:handle_cast/2
.
enter_loop(Module, Options, State)
enter_loop(Module, Options, State, ServerName)
enter_loop(Module, Options, State, Timeout)
enter_loop(Module, Options, State, ServerName, Timeout)
Module = atom()
Options = [Option]
Option = {debug,Dbgs}
Dbgs = [Dbg]
Dbg = trace | log | statistics
| {log_to_file,FileName} | {install,{Func,FuncState}}
State = term()
ServerName = {local,Name} | {global,GlobalName}
| {via,Module,ViaName}
Name = atom()
GlobalName = ViaName = term()
Timeout = int() | infinity
Makes an existing process into a gen_server
process. Does not
return, instead the calling process enters the gen_server
process receive
loop and becomes a gen_server
process. The process
must have been started using one of the start functions in
proc_lib(3)
. The user is
responsible for any initialization of the process, including
registering a name for it.
This function is useful when a more complex initialization procedure
is needed than the gen_server
process behavior provides.
Module
, Options
, and ServerName
have
the same meanings as when calling
start[_link]/3,4
.
However, if ServerName
is specified, the process must
have been registered accordingly before this function
is called.
State
and Timeout
have the same meanings as in
the return value of
Module:init/1
.
The callback module Module
does not need to
export an init/1
function.
The function fails if the calling process was not started by a
proc_lib
start function, or if it is not registered
according to ServerName
.
multi_call(Name, Request) -> Result
multi_call(Nodes, Name, Request) -> Result
multi_call(Nodes, Name, Request, Timeout) -> Result
Nodes = [Node]
Node = atom()
Name = atom()
Request = term()
Timeout = int()>=0 | infinity
Result = {Replies,BadNodes}
Replies = [{Node,Reply}]
Reply = term()
BadNodes = [Node]
Makes a synchronous call to all gen_server
processes locally
registered as Name
at the specified nodes by first
sending a request to every node and then waits for
the replies. The gen_server
process calls
Module:handle_call/3
to handle the request.
The function returns a tuple {Replies,BadNodes}
, where
Replies
is a list of {Node,Reply}
and
BadNodes
is a list of node that either did not exist,
or where the gen_server
Name
did not exist or did not
reply.
Nodes
is a list of node names to which the request
is to be sent. Default value is the list of all known nodes
[node()|nodes()]
.
Name
is the locally registered name of each
gen_server
process.
Request
is any term that is passed as one of
the arguments to Module:handle_call/3
.
Timeout
is an integer greater than zero that
specifies how many milliseconds to wait for each reply, or
the atom infinity
to wait indefinitely. Defaults
to infinity
. If no reply is received from a node within
the specified time, the node is added to BadNodes
.
When a reply Reply
is received from the gen_server
process at a node Node
, {Node,Reply}
is added to
Replies
. Reply
is defined in the return value of
Module:handle_call/3
.
Warning!
If one of the nodes cannot process monitors, for example,
C or Java nodes, and the gen_server
process is not started
when the requests are sent, but starts within 2 seconds,
this function waits the whole Timeout
,
which may be infinity.
This problem does not exist if all nodes are Erlang nodes.
To prevent late answers (after the time-out) from polluting the message queue of the caller, a middleman process is used to do the calls. Late answers are then discarded when they arrive to a terminated process.
reply(Client, Reply) -> Result
Client - see below
Reply = term()
Result = term()
This function can be used by a gen_server
process to
explicitly send a reply to a client that called
call/2,3
or
multi_call/2,3,4
,
when the reply cannot be defined in the return value of
Module:handle_call/3
.
Client
must be the From
argument provided to
the callback function. Reply
is any term
given back to the client as the return value of
call/2,3
or multi_call/2,3,4
.
The return value Result
is not further defined, and
is always to be ignored.
start(Module, Args, Options) -> Result
start(ServerName, Module, Args, Options) -> Result
ServerName = {local,Name} | {global,GlobalName}
| {via,Module,ViaName}
Name = atom()
GlobalName = ViaName = term()
Module = atom()
Args = term()
Options = [Option]
Option = {debug,Dbgs} | {timeout,Time} | {spawn_opt,SOpts}
Dbgs = [Dbg]
Dbg = trace | log | statistics | {log_to_file,FileName} | {install,{Func,FuncState}}
SOpts = [term()]
Result = {ok,Pid} | ignore | {error,Error}
Pid = pid()
Error = {already_started,Pid} | term()
Creates a standalone gen_server
process, that is, a
gen_server
process that is not part of a supervision tree
and thus has no supervisor.
For a description of arguments and return values, see
start_link/3,4
.
start_link(Module, Args, Options) -> Result
start_link(ServerName, Module, Args, Options) -> Result
ServerName = {local,Name} | {global,GlobalName}
| {via,Module,ViaName}
Name = atom()
GlobalName = ViaName = term()
Module = atom()
Args = term()
Options = [Option]
Option = {debug,Dbgs} | {timeout,Time} | {spawn_opt,SOpts}
Dbgs = [Dbg]
Dbg = trace | log | statistics | {log_to_file,FileName} | {install,{Func,FuncState}}
SOpts = [term()]
Result = {ok,Pid} | ignore | {error,Error}
Pid = pid()
Error = {already_started,Pid} | term()
Creates a gen_server
process as part of a supervision tree.
This function is to be called, directly or indirectly, by
the supervisor. For example, it ensures that
the gen_server
process is linked to the supervisor.
The gen_server
process calls
Module:init/1
to
initialize. To ensure a synchronized startup procedure,
start_link/3,4
does not return until
Module:init/1
has returned.
-
If
ServerName={local,Name}
, thegen_server
process is registered locally asName
usingregister/2
. -
If
ServerName={global,GlobalName}
, thegen_server
process id registered globally asGlobalName
usingglobal:register_name/2
If no name is provided, thegen_server
process is not registered. -
If
ServerName={via,Module,ViaName}
, thegen_server
process registers with the registry represented byModule
. TheModule
callback is to export the functionsregister_name/2
,unregister_name/1
,whereis_name/1
, andsend/2
, which are to behave like the corresponding functions inglobal
. Thus,{via,global,GlobalName}
is a valid reference.
Module
is the name of the callback module.
Args
is any term that is passed as
the argument to
Module:init/1
.
-
If option
{timeout,Time}
is present, thegen_server
process is allowed to spendTime
milliseconds initializing or it is terminated and the start function returns{error,timeout}
. -
If option
{debug,Dbgs}
is present, the correspondingsys
function is called for each item inDbgs
; seesys(3)
. -
If option
{spawn_opt,SOpts}
is present,SOpts
is passed as option list to thespawn_opt
BIF, which is used to spawn thegen_server
process; seespawn_opt/2
.
Note!
Using spawn option monitor
is not
allowed, it causes the function to fail with reason
badarg
.
If the gen_server
process is successfully created and
initialized, the function returns {ok,Pid}
, where Pid
is the pid of the gen_server
process. If a process with the
specified ServerName
exists already, the function returns
{error,{already_started,Pid}}
, where Pid
is
the pid of that process.
If Module:init/1
fails with Reason
,
the function returns {error,Reason}
. If
Module:init/1
returns {stop,Reason}
or
ignore
, the process is terminated and the function
returns {error,Reason}
or ignore
, respectively.
stop(ServerRef) -> ok
stop(ServerRef, Reason, Timeout) -> ok
ServerRef = Name | {Name,Node} | {global,GlobalName}
| {via,Module,ViaName} | pid()
Node = atom()
GlobalName = ViaName = term()
Reason = term()
Timeout = int()>0 | infinity
Orders a generic server to exit with the specified Reason
and waits for it to terminate. The gen_server
process calls
Module:terminate/2
before exiting.
The function returns ok
if the server terminates
with the expected reason. Any other reason than normal
,
shutdown
, or {shutdown,Term}
causes an
error report to be issued using
error_logger:format/2
.
The default Reason
is normal
.
Timeout
is an integer greater than zero that
specifies how many milliseconds to wait for the server to
terminate, or the atom infinity
to wait
indefinitely. Defaults to infinity
. If the
server has not terminated within the specified time, a
timeout
exception is raised.
If the process does not exist, a noproc
exception
is raised.
Callback Functions
The following functions
are to be exported from a gen_server
callback module.
Functions
Module:code_change(OldVsn, State, Extra) -> {ok, NewState} | {error, Reason}
OldVsn = Vsn | {down, Vsn}
Vsn = term()
State = NewState = term()
Extra = term()
Reason = term()
This function is called by a gen_server
process when it is
to update its internal state during a release upgrade/downgrade,
that is, when the instruction {update,Module,Change,...}
,
where Change={advanced,Extra}
, is specifed in
the appup
file. For more information, see section
Release Handling Instructions in OTP Design Principles.
For an upgrade, OldVsn
is Vsn
, and
for a downgrade, OldVsn
is
{down,Vsn}
. Vsn
is defined by the vsn
attribute(s) of the old version of the callback module
Module
. If no such attribute is defined, the version
is the checksum of the Beam file.
State
is the internal state of the gen_server
process.
Extra
is passed "as is" from the {advanced,Extra}
part of the update instruction.
If successful, the function must return the updated internal state.
If the function returns {error,Reason}
, the ongoing
upgrade fails and rolls back to the old release.
Module:format_status(Opt, [PDict, State]) -> Status
Opt = normal | terminate
PDict = [{Key, Value}]
State = term()
Status = term()
Note!
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.
This function is called by a gen_server
process in the
following situations:
-
One of
sys:get_status/1,2
is invoked to get thegen_server
status.Opt
is set to the atomnormal
. -
The
gen_server
process terminates abnormally and logs an error.Opt
is set to the atomterminate
.
This function is useful for changing the form and
appearance of the gen_server
status for these cases. A
callback module wishing to change
the sys:get_status/1,2
return value, as well as how
its status appears in termination error logs, exports an
instance of format_status/2
that returns a term
describing the current status of the gen_server
process.
PDict
is the current value of the process dictionary of
the gen_server
process..
State
is the internal state of the gen_server
process.
The function is to return Status
, a term that
changes the details of the current state and status of
the gen_server
process. There are no restrictions on the
form Status
can take, but for
the sys:get_status/1,2
case (when Opt
is normal
), the recommended form for
the Status
value is [{data, [{"State",
Term}]}]
, where Term
provides relevant details of
the gen_server
state. Following this recommendation is not
required, but it makes the callback module status
consistent with the rest of the sys:get_status/1,2
return value.
One use for this function is to return compact alternative state representations to avoid that large state terms are printed in log files.
Module:handle_call(Request, From, State) -> Result
Request = term()
From = {pid(),Tag}
State = term()
Result = {reply,Reply,NewState} | {reply,Reply,NewState,Timeout}
| {reply,Reply,NewState,hibernate}
| {noreply,NewState} | {noreply,NewState,Timeout}
| {noreply,NewState,hibernate}
| {stop,Reason,Reply,NewState} | {stop,Reason,NewState}
Reply = term()
NewState = term()
Timeout = int()>=0 | infinity
Reason = term()
Whenever a gen_server
process receives a request sent using
call/2,3
or
multi_call/2,3,4
,
this function is called to handle the request.
Request
is the Request
argument provided
to call
or multi_call
.
From
is a tuple {Pid,Tag}
, where Pid
is
the pid of the client and Tag
is a unique tag.
State
is the internal state of the gen_server
process.
-
If
{reply,Reply,NewState}
is returned,{reply,Reply,NewState,Timeout}
or{reply,Reply,NewState,hibernate}
,Reply
is given back toFrom
as the return value ofcall/2,3
or included in the return value ofmulti_call/2,3,4
. Thegen_server
process then continues executing with the possibly updated internal stateNewState
.For a description of
Timeout
andhibernate
, seeModule:init/1
. -
If
{noreply,NewState}
is returned,{noreply,NewState,Timeout}
, or{noreply,NewState,hibernate}
, thegen_server
process continues executing withNewState
. Any reply toFrom
must be specified explicitly usingreply/2
. -
If
{stop,Reason,Reply,NewState}
is returned,Reply
is given back toFrom
. -
If
{stop,Reason,NewState}
is returned, any reply toFrom
must be specified explicitly usingreply/2
. Thegen_server
process then callsModule:terminate(Reason,NewState)
and terminates.
Module:handle_cast(Request, State) -> Result
Request = term()
State = term()
Result = {noreply,NewState} | {noreply,NewState,Timeout}
| {noreply,NewState,hibernate}
| {stop,Reason,NewState}
NewState = term()
Timeout = int()>=0 | infinity
Reason = term()
Whenever a gen_server
process receives a request sent using
cast/2
or
abcast/2,3
,
this function is called to handle the request.
For a description of the arguments and possible return values, see
Module:handle_call/3
.
Module:handle_info(Info, State) -> Result
Info = timeout | term()
State = term()
Result = {noreply,NewState} | {noreply,NewState,Timeout}
| {noreply,NewState,hibernate}
| {stop,Reason,NewState}
NewState = term()
Timeout = int()>=0 | infinity
Reason = normal | term()
This function is called by a gen_server
process when a
time-out occurs or when it receives any other message than a
synchronous or asynchronous request (or a system message).
Info
is either the atom timeout
, if a time-out
has occurred, or the received message.
For a description of the other arguments and possible return values,
see
Module:handle_call/3
.
Module:init(Args) -> Result
Args = term()
Result = {ok,State} | {ok,State,Timeout} | {ok,State,hibernate}
| {stop,Reason} | ignore
State = term()
Timeout = int()>=0 | infinity
Reason = term()
Whenever a gen_server
process is started using
start/3,4
or
start_link/3,4
,
this function is called by the new process to initialize.
Args
is the Args
argument provided to the start
function.
If the initialization is successful, the function is to
return {ok,State}
, {ok,State,Timeout}
, or
{ok,State,hibernate}
, where State
is the internal
state of the gen_server
process.
If an integer time-out value is provided, a time-out occurs
unless a request or a message is received within
Timeout
milliseconds. A time-out is represented by
the atom timeout
, which is to be handled by the
Module:handle_info/2
callback function. The atom
infinity
can be used to wait indefinitely, this is
the default value.
If hibernate
is specified instead of a time-out value,
the process goes into
hibernation when waiting for the next message to arrive (by calling
proc_lib:hibernate/3
).
If the initialization fails, the function is to return
{stop,Reason}
, where Reason
is any term, or
ignore
.
Module:terminate(Reason, State)
Reason = normal | shutdown | {shutdown,term()} | term()
State = term()
This function is called by a gen_server
process when it is
about to terminate. It is to be the opposite of
Module:init/1
and do any necessary cleaning up. When it returns,
the gen_server
process terminates with Reason
.
The return value is ignored.
Reason
is a term denoting the stop reason and State
is the internal state of the gen_server
process.
Reason
depends on why the gen_server
process is
terminating. If it is because another callback function has returned
a stop tuple {stop,..}
, Reason
has
the value specified in that tuple. If it is because of a failure,
Reason
is the error reason.
If the gen_server
process is part of a supervision tree and
is ordered by its supervisor to terminate, this function is
called with Reason=shutdown
if the following
conditions apply:
-
The
gen_server
process has been set to trap exit signals. -
The shutdown strategy as defined in the child specification of the supervisor is an integer time-out value, not
brutal_kill
.
Even if the gen_server
process is not part of a
supervision tree, this function is called if it receives an
'EXIT'
message from its parent. Reason
is the same
as in the 'EXIT'
message.
Otherwise, the gen_server
process terminates immediately.
Notice that for any other reason than normal
,
shutdown
, or {shutdown,Term}
, the gen_server
process is assumed to terminate because of an error and
an error report is issued using
error_logger:format/2
.
See Also
gen_event(3)
,
gen_fsm(3)
,
gen_statem(3)
,
proc_lib(3)
,
supervisor(3)
,
sys(3)