考虑这样简单的GenServer模块:
defmodule Crap do
use GenServer
... #All the needed crap
def handle_info(:kill_me_pls, state) do
GenServer.stop(self)
{:noreply, state}
end
def terminate(_, state) do
IO.inspect "Look! I'm dead."
end
end
考虑将这些表达式放入repl:
{:ok, pid} = Crap.start_link
send_message_to_that_pid
这就是我的Conceirns开始的地方,因为Process.alive? pid
返回true,但是进程没有响应,并且terminate
没有被调用,尽管如果我调用GenServer.stop(pid)
在repl中调用'干净的'进程(没有收到杀死消息)正确杀死它。如果停止调用收到的进程:kill_me_pls消息挂起了repl。
答案 0 :(得分:9)
从内部停止GenServer"的正确方法"是从{:stop, reason, new_state}
返回handle_*
或{:stop, reason, reply, new_state}
的{{1}}值。您的代码失败的原因是调用handle_call
向GenServer发送一条特殊消息,并且由于GenServer是一个进程并且当前位于GenServer.stop
,因此它无法响应handle_info
调用,所以你的进程会挂起/造成死锁。
这是正确的方法:
stop
您可以详细了解可能的返回值,请查看documentation of GenServer中标题def handle_info(:kill_me_pls, state) do
{:stop, :normal, state}
end
下的文字。
演示:
Return values