Here is a simple test GenServer:
defmodule T do
use GenServer
def start() do
IO.puts("T.start")
GenServer.start(__MODULE__, [])
end
def start_link() do
IO.puts("T.start_link")
GenServer.start_link(__MODULE__, [])
end
@impl true
def init(state) do
IO.puts("T.init with trap_exit enable ")
Process.flag(:trap_exit, true)
{:ok, state}
end
@impl true
def handle_info(msg, state) do
IO.inspect(msg, label: "T.handle_info")
{:noreply, state}
end
@impl true
def terminate(reason, state) do
IO.inspect(reason, label: "T.terminate")
end
end
And here are two iex
executions that disorientate my understanding of GenServer operation with exit signal:
Interactive Elixir (1.13.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> self()
#PID<0.126.0>
iex(2)> Process.flag(:trap_exit, true)
false
iex(3)> {:ok, p} = T.start_link()
T.start_link
T.init with trap_exit enable
{:ok, #PID<0.130.0>}
iex(4)> Process.exit(p, :err)
true
T.terminate: :err
iex(5)>
17:39:15.736 [error] GenServer #PID<0.130.0> terminating
** (stop) :err
Last message: {:EXIT, #PID<0.126.0>, :err}
State: []
nil
iex(6)> Process.alive?(p)
false
iex(7)> flush()
{:EXIT, #PID<0.130.0>, :err}
:ok
Interactive Elixir (1.13.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> self()
#PID<0.126.0>
iex(2)> Process.flag(:trap_exit, true)
false
iex(3)> {:ok, p} = T.start()
T.start
T.init with trap_exit enable
{:ok, #PID<0.130.0>}
iex(4)> Process.link(p)
true
iex(5)> Process.exit(p, :err)
T.handle_info: {:EXIT, #PID<0.126.0>, :err}
true
iex(6)> Process.alive?(p)
true
iex(7)> flush()
:ok
As you can see, GenServer
started with start_link
and with start
and then link
behave differently on the exit signal.
The second variant behaves as I suppose it must be. If process set :trap_exit
, then exit signal (if it is not :kill
) converted to a message.
But what is wrong with the first variant? Why does the exit signal not convert to a message though that process set :trap_exit
?
I read all the doc about this topic that I could find, but unfortunately, I can’t find the answer. Could anyone please point me to corresponding documentation or at last explain this behavior.