Links
The most common form of spawning in Elixir is actually via spawn_link/1
. Before we show an example with spawn_link/1
, let’s try to see what happens when a process fails:
iex> spawn fn -> raise "oops" end
#PID<0.58.0>
[error] Error in process <0.58.0> with exit value: ...
It merely logged an error but the spawning process is still running. That’s because processes are isolated. If we want the failure in one process to propagate to another one, we should link them. This can be done with spawn_link/1
:
iex> spawn_link fn -> raise "oops" end
#PID<0.41.0>
** (EXIT from #PID<0.41.0>) an exception was raised:
** (RuntimeError) oops
:erlang.apply/2
When a failure happens in the shell, the shell automatically traps the failure and shows it nicely formatted. In order to understand what would really happen in our code, let’s use spawn_link/1
inside a file and run it:
# spawn.exs
spawn_link fn -> raise "oops" end
receive do
:hello -> "let's wait until the process fails"
end
$ elixir spawn.exs
** (EXIT from #PID<0.47.0>) an exception was raised:
** (RuntimeError) oops
spawn.exs:1: anonymous fn/0 in :elixir_compiler_0.__FILE__/1
This time the process failed and brought the parent process down as they are linked. Linking can also be done manually by calling Process.link/1
. We recommend that you take a look at the Process
module for other functionality provided by processes.
Processes and links play an important role when building fault-tolerant systems. In Elixir applications, we often link our processes to supervisors which will detect when a process dies and start a new process in its place. This is only possible because processes are isolated and don’t share anything by default. And since processes are isolated, there is no way a failure in a process will crash or corrupt the state of another.
While other languages would require us to catch/handle exceptions, in Elixir we are actually fine with letting processes fail because we expect supervisors to properly restart our systems. “Failing fast” is a common philosophy when writing Elixir software!
spawn/1
and spawn_link/1
are the basic primitives for creating processes in Elixir. Although we have used them exclusively so far, most of the time we are going to use abstractions that build on top of them. Let’s see the most common one, called tasks.