考虑这样简单的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
Run Code Online (Sandbox Code Playgroud)
并考虑将这些表达式放入repl中:
{:ok, pid} = Crap.start_link
send_message_to_that_pid
Run Code Online (Sandbox Code Playgroud)
这是我的conceirns开始的地方,因为Process.alive? pid返回true,但是进程没有响应而且terminate没有被调用,尽管如果我GenServer.stop(pid)在'clean'进程中调用repl(没有收到kill消息)就可以正常杀死它.如果停止调用收到的进程:kill_me_pls消息挂起了repl.
正确的做法应该停止GenServer"从内部"是返回一个{:stop, reason, new_state}由值handle_*或{:stop, reason, reply, new_state}从handle_call.您的代码失败的原因是调用GenServer.stop向GenServer发送特殊消息,并且由于GenServer是单个进程并且当前处于进程中handle_info,因此它无法响应该stop调用,因此您的进程挂起/创建死锁.
这是正确的方法:
def handle_info(:kill_me_pls, state) do
{:stop, :normal, state}
end
Run Code Online (Sandbox Code Playgroud)
你可以阅读更多有关可能的返回值,检查出的标题下的文本Return values中 GenServer的文档.
演示:
iex(1)> defmodule Crap do
...(1)> use GenServer
...(1)>
...(1)> def handle_info(:kill_me_pls, state) do
...(1)> {:stop, :normal, state}
...(1)> end
...(1)>
...(1)> def terminate(_, state) do
...(1)> IO.inspect "Look! I'm dead."
...(1)> end
...(1)> end
iex(2)> {:ok, pid} = GenServer.start Crap, []
{:ok, #PID<0.98.0>}
iex(3)> send(pid, :kill_me_pls)
"Look! I'm dead."
:kill_me_pls
iex(4)> Process.alive?(pid)
false
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1602 次 |
| 最近记录: |