我使用poolboy创建了几乎空工作者的简单应用程序,但是当我停止应用程序时,我看到由lager打印的以下错误:
10:50:26.363 [error] Supervisor {<0.236.0>,poolboy_sup} had child test_worker started with test_worker:start_link([]) at undefined exit with reason shutdown in context shutdown_error
导致此错误的原因是什么?如何解决此问题?
监:
-module(test_sup).
-behaviour(supervisor).
-export([start_link/0, init/1]).
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
init([]) ->
ChildSpecs = [pool_spec()],
{ok, {{one_for_one, 1000, 3600}, ChildSpecs}}.
pool_spec() ->
Name = test_pool,
PoolArgs = [{name, {local, Name}},
{worker_module, test_worker},
{size, 10},
{max_overflow, 20}],
poolboy:child_spec(Name, PoolArgs, []).
工人:
-module(test_worker).
-behaviour(gen_server).
-behaviour(poolboy_worker).
-export([start_link/1]).
-export([init/1, handle_call/3, handle_cast/2,
handle_info/2, terminate/2, code_change/3]).
-record(state, {}).
start_link([]) ->
gen_server:start_link(?MODULE, [], []).
init([]) ->
{ok, #state{}}.
handle_call(_Request, _From, State) ->
{reply, _Reply = ok, State}.
handle_cast(_Msg, State) ->
{noreply, State}.
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
应用程序的其余部分非常标准。
Erlang:R16B02
Poolboy:1.0.1
Lager:撰写问题时主人的最新版本(822062478a223313dce30e5a45e30a50a4b7dc4e)
答案 0 :(得分:8)
您看到的错误实际上不是错误,而是lager生成的错误报告。此报告似乎是由 poolboy中的错误引起的。
你可以:
停止OTP应用程序时应该发生的事情是监督树用于终止所有进程,最好是优雅地进行。默认的方法是向受监督的进程发送shutdown
信号,如果这在一段时间后不起作用,则残酷地杀死它们。一切顺利,你永远不会得到任何报告。
有两个Erlang细微之处可以理解这个错误:
normal
以外的原因),所有链接的进程都会以相同的原因终止。这个原语是OTP监督的基础。normal
,但不包括将无条件终止它的kill
。与陷阱退出相结合的链接通常用于监视进程终止,还有在监视进程终止时终止受监视进程的额外好处。例如,如果主管终止,其子女将被终止。还存在不对称的monitor
机制。
在这里,你的主管(实现test_sup行为)终止的原因是shutdown
,应该是这样。主管行为实际上捕获了退出,当它收到shutdown
信号时,它会尝试根据其关闭策略终止其子节点。在这里,您使用默认策略,即首次尝试向孩子发送shutdown
信号。因此,您的主管将shutdown
信号发送给其唯一的孩子。
Poolboy在这里引入了它的魔力,你的主管的孩子实际上是一个gen_server
和poolboy
回调模块。它应该关闭池并优雅地终止。
此模块已链接到pool supervisor,但也链接到the workers。这个令人惊讶的实现选择可能是池的崩溃(poolboy gen_server
)将终止工作者。但是,这是bug的来源,非对称监视器可能更有意义。由于主管已经与poolboy gen_server
相关联,因此终止poolboy
流程最终会导致工作人员终止。
链接到工作人员的后果是他们还获得shutdown
退出信号,该信号最初被定向到poolboy
进程。他们被终止了。工作人员的主管(实施poolboy_sup
回调)认为此终止是异常的,因为它本身并不发送信号。因此,主管会报告关闭,此处由lager记录。
poolboy
traps exits无法阻止shutdown
信号传播的事实。当接收到信号时,该过程不会立即终止,但它会将其作为消息接收。 gen_server
拦截此消息,调用terminate/2
回调函数,然后调用terminates with shutdown
,最终将信号传播到所有链接的进程。
如果无法选择link to workers,则修复此错误的方法是取消关联terminate handler中的所有工作人员。
答案 1 :(得分:1)
你如何停止申请?也许主管应该有一个停止/ 1功能?例如,见
http://www.erlang.org/doc/apps/kernel/application.html#stop-1