我创建了一个GameSupervisor监控模块,用于动态创建实例GameServer(GenServer)的子级。我可以看到GameServer的start_link方法在调用GameSupervisor.start函数时被调用,但它不能保持pid活着。如果重启策略设置为临时,iex中的Process.alive?(pid)总是返回false。如果我将重启设置为暂时或永久,当我在该pid上调用GenServer.cast时,它会再次调用GameServer.start_link。
调用start_child不会自动将pid添加到监督树并保持活动状态吗?
GameSupervisor.ex
defmodule Prest.GameSupervisor do
alias Prest.GameServer
use Supervisor
@name :game_sup
def start_link() do
IO.puts "start link"
Supervisor.start_link(__MODULE__, [], [name: @name])
end
def start(uid) do
IO.puts "start bucket"
{:ok, child} = Supervisor.start_child(@name, [uid])
end
def init([]) do
IO.puts "init sup"
children = [
worker(GameServer, [], restart: :transient)
]
supervise(children, strategy: :simple_one_for_one)
end
end
GameServer.ex
defmodule Prest.GameServer do
use GenServer
# Client API
def start_link(uid) do
IO.puts "start game server"
GenServer.start_link(__MODULE__, uid, [])
end
def post(pid, event_id) do
:gen_server.cast(pid, {:event, event_id})
end
# Server API
def init(uid) do
{:ok, {uid, [], []}}
end
def handle_cast({:event, event_id}, state) do
#state = [event_id|state]
{:noreply, "ok", state}
end
end
由于
答案 0 :(得分:3)
根据the docs:
:permanent
进程正常终止,也始终重新启动:transient
进程。 :temporary
进程异常终止时才会重新启动它。 GameServer
进程。很可能,您的{:ok, pid}
进程因某种原因而崩溃,并且主管正在以其配置方式处理重启。
要调试此操作,您需要检查日志(可能只输出到终端)以查看进程崩溃的原因。如果您能够获得handle_cast
,那么它可能不会在init上崩溃,这意味着handle_call
,handle_info
或handle_cast
子句负责崩溃。
没有代码,很难提供更具体的帮助。
在这种情况下,看起来{:noreply, state}
的返回值很差。它should return {:noreply, "ok", state}
,但正在返回handle_call
。这通常是由于将handle_cast
更改为vertical-align: top;
,并忘记删除回复值。