12 Processes
12.1 Processes
Erlang is designed for massive concurrency. Erlang processes are lightweight (grow and shrink dynamically) with small memory footprint, fast to create and terminate, and the scheduling overhead is low.
12.2 Process Creation
A process is created by calling spawn:
spawn(Module, Name, Args) -> pid() Module = Name = atom() Args = [Arg1,...,ArgN] ArgI = term()
spawn creates a new process and returns the pid.
The new process starts executing in Module:Name(Arg1,...,ArgN) where the arguments are the elements of the (possible empty) Args argument list.
There exist a number of other spawn BIFs, for example, spawn/4 for spawning a process at another node.
12.3 Registered Processes
Besides addressing a process by using its pid, there are also BIFs for registering a process under a name. The name must be an atom and is automatically unregistered if the process terminates:
BIF | Description |
register(Name, Pid) | Associates the name Name, an atom, with the process Pid. |
registered() | Returns a list of names that have been registered using register/2. |
whereis(Name) | Returns the pid registered under Name, or undefined if the name is not registered. |
12.4 Process Termination
When a process terminates, it always terminates with an exit reason. The reason can be any term.
A process is said to terminate normally, if the exit reason is the atom normal. A process with no more code to execute terminates normally.
A process terminates with an exit reason {Reason,Stack} when a run-time error occurs. See Exit Reasons.
A process can terminate itself by calling one of the following BIFs:
- exit(Reason)
- erlang:error(Reason)
- erlang:error(Reason, Args)
The process then terminates with reason Reason for exit/1 or {Reason,Stack} for the others.
A process can also be terminated if it receives an exit signal with another exit reason than normal, see Error Handling.
12.5 Message Sending
Processes communicate by sending and receiving messages. Messages are sent by using the send operator ! and received by calling receive.
Message sending is asynchronous and safe, the message is guaranteed to eventually reach the recipient, provided that the recipient exists.
12.6 Links
Two processes can be linked to each other. Also a process and a port that reside on the same node can be linked to each other. A link beteen two processes can be created if one of them calls the link/1 BIF with the process identifier of the other process as argument. Links can also be created using one the following spawn BIFs spawn_link(), spawn_opt(), or spawn_request(). The spawn operation and the link operation will be performed atomically, in these cases.
If one of the participants of a link terminates, it will send an exit signal to the other participant. The exit signal will contain the exit reason of the terminated participant.
A link can be removed by calling the unlink/1 BIF.
Links are bidirectional and there can only be one link between two processes. Repeated calls to link() have no effect. Either one of the involved processes may create or remove a link.
Links are used to monitor the behaviour of other processes, see Error Handling.
12.7 Error Handling
Erlang has a built-in feature for error handling between processes. Terminating processes emit exit signals to all linked processes, which can terminate as well or handle the exit in some way. This feature can be used to build hierarchical program structures where some processes are supervising other processes, for example, restarting them if they terminate abnormally.
See OTP Design Principles for more information about OTP supervision trees, which use this feature.
Sending Exit Signals
When a process or port terminates it will send exit signals to all processes and ports that it is linked to. The exit signal will contain the following information:
- Sender identifier
The process or port identifier of the process or port that terminated.
- Receiver identifier
The process or port identifier of the process or port which the exit signal is sent to.
- The link flag
This flag will be set indicating that the exit signal was sent due to a link.
- Exit reason
-
The exit reason of the process or port that terminated or the atom:
noproc in case no process or port was found when setting up a link in a preceeding call to the link(PidOrPort) BIF. The process or port identified as sender of the exit signal will equal the PidOrPort argument passed to link/1.
noconnection in case the linked processes resides on different nodes and the connection between the nodes was lost or could not be established. The process or port identified as sender of the exit signal might in this case still be alive.
Exit signals can also be sent explicitly by calling the exit(PidOrPort, Reason) BIF. The exit signal is sent to the process or port identified by the PidOrPort argument. The exit signal sent will contain the following information:
- Sender identifier
The process identifier of the process that called exit/2.
- Receiver identifier
The process or port identifier of the process or port which the exit signal is sent to.
- The link flag
This flag will not be set, indicating that this exit signal was not sent due to a link.
- Exit reason
The term passed as Reason in the call to exit/2. If Reason is the atom kill, the receiver cannot trap the exit signal and will unconditionally terminate when it receives the signal.
Receiving Exit Signals
What happens when a process receives an exit signal depends on:
The trap exit state of the receiver at the time when the exit signal is received.
The exit reason of the exit signal.
The sender of the exit signal.
The state of the link flag of the exit signal. If the link flag is set, the exit signal was sent due to a link; otherwise, the exit signal was sent by a call to the exit/2 BIF.
If the link flag is set, what happens also depends on whether the link is still active or not when the exit signal is received.
Based on the above states, the following will happen when an exit signal is received by a process:
-
The exit signal is silently dropped if:
the link flag of the exit signal is set and the corresponding link has been deactivated.
the exit reason of the exit signal is the atom normal, the receiver is not trapping exits, and the receiver and sender are not the same process.
-
The receiving process is terminated if:
the link flag of the exit signal is not set, and the exit reason of the exit signal is the atom kill. The receiving process will terminate with the atom killed as exit reason.
the receiver is not trapping exits, and the exit reason is something other than the atom normal. Also, if the link flag of the exit signal is set, the link also needs to be active otherwise the exit signal will be dropped. The exit reason of the receiving process will equal the exit reason of the exit signal. Note that if the link flag is set, an exit reason of kill will not be converted to killed.
the exit reason of the exit signal is the atom normal and the sender of the exit signal is the same process as the receiver. The link flag cannot be set in this case. The exit reason of the receiving process will be the atom normal.
-
The exit signal is converted to a message signal and moved into the message queue of the receiver, if the receiver is trapping exits, the link flag of the exit signal is:
not set, and the exit reason of the signal is not the atom kill.
set, and the corresponding link is active. Note that an exit reason of kill will not terminate the process in this case and it will not be converted to killed.
The converted message will be on the form {'EXIT', SenderID, Reason} where Reason equals the exit reason of the exit signal and SenderID is the identifier of the process or port that sent the exit signal.
12.8 Monitors
An alternative to links are monitors. A process Pid1 can create a monitor for Pid2 by calling the BIF erlang:monitor(process, Pid2). The function returns a reference Ref.
If Pid2 terminates with exit reason Reason, a 'DOWN' message is sent to Pid1:
{'DOWN', Ref, process, Pid2, Reason}
If Pid2 does not exist, the 'DOWN' message is sent immediately with Reason set to noproc.
Monitors are unidirectional. Repeated calls to erlang:monitor(process, Pid) creates several independent monitors, and each one sends a 'DOWN' message when Pid terminates.
A monitor can be removed by calling erlang:demonitor(Ref).
Monitors can be created for processes with registered names, also at other nodes.
12.9 Process Dictionary
Each process has its own process dictionary, accessed by calling the following BIFs:
put(Key, Value) get(Key) get() get_keys(Value) erase(Key) erase()