从内部杀死GenServer

时间:2016-09-28 18:13:16

标签: elixir

考虑这样简单的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。

1 个答案:

答案 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