Erlang supervisor 不重启 child
Erlang supervisor does not restart child
我正在尝试了解 erlang 主管。我有一个简单的 printer process
,每 3 秒打印一次 hello。我还有一个主管,如果发生任何异常,必须重新启动 printer process
。
这是我的代码:
test.erl:
-module(test).
-export([start_link/0]).
start_link() ->
io:format("started~n"),
Pid = spawn_link(fun() -> loop() end),
{ok, Pid}.
loop() ->
timer:sleep(3000),
io:format("hello~n"),
loop().
test_sup.erl:
-module(test_sup).
-behaviour(supervisor).
-export([start_link/0]).
-export([init/1]).
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
init(_Args) ->
SupFlags = #{strategy => one_for_one, intensity => 1, period => 5},
ChildSpecs = [#{id => test,
start => {test, start_link, []},
restart => permanent,
shutdown => brutal_kill,
type => worker,
modules => [test]}],
{ok, {SupFlags, ChildSpecs}}.
现在我 运行 这个程序并使用 test_sup:start_link().
命令启动主管,几秒钟后,我引发了一个异常。为什么supervisor不重启printer process
?
这是 shell 输出:
1> test_sup:start_link().
started
{ok,<0.36.0>}
hello
hello
hello
hello
2> erlang:error(err).
=ERROR REPORT==== 13-Dec-2016::00:57:10 ===
** Generic server test_sup terminating
** Last message in was {'EXIT',<0.34.0>,
{err,
[{erl_eval,do_apply,6,
[{file,"erl_eval.erl"},{line,674}]},
{shell,exprs,7,
[{file,"shell.erl"},{line,686}]},
{shell,eval_exprs,7,
[{file,"shell.erl"},{line,641}]},
{shell,eval_loop,3,
[{file,"shell.erl"},{line,626}]}]}}
** When Server state == {state,
{local,test_sup},
one_for_one,
[{child,<0.37.0>,test,
{test,start_link,[]},
permanent,brutal_kill,worker,
[test]}],
undefined,1,5,[],0,test_sup,[]}
** Reason for termination ==
** {err,[{erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,674}]},
{shell,exprs,7,[{file,"shell.erl"},{line,686}]},
{shell,eval_exprs,7,[{file,"shell.erl"},{line,641}]},
{shell,eval_loop,3,[{file,"shell.erl"},{line,626}]}]}
** exception error: err
当您执行 erlang:error(err).
时,您正在终止调用进程,您的 shell.
因为你已经用start_link启动了supervisor,它也被kill掉了,loop也一样。
shell自动重启(多亏了一些监督者),但是没有人重启你的测试监督者,这无法重启循环。
要进行此测试,您应该这样做:
在模块测试中:
start_link() ->
Pid = spawn_link(fun() -> loop() end),
io:format("started ~p~n",[Pid]),
{ok, Pid}.
你会得到一个提示:
started <0,xx,0>
其中<0,xx,0>
是循环pid,在shell中可以调用
exit(pid(0,xx,0), err).
仅终止循环。
这是您使用文件创建的架构:
test_sup (supervisor)
^
|
v
test (worker)
然后您通过在 shell 中调用 start_link()
来启动您的主管。这将创建另一个双向 link:
shell
^
|
v
test_sup (supervisor)
^
|
v
test (worker)
双向link,如果一方死亡,另一方也被杀死。
当您 运行 erlang:error
时,您会导致 shell 出错!
你的 shell 被 link 发送给你的主管,所以 Erlang 杀死主管作为回应。通过连锁反应,你的工人也被杀了。
我认为您打算将错误情况发送给您的工作人员而不是 shell:
- 确定您的工人的 PID:
supervisor:which_children
- 在工人的 Pid 上调用
erlang:exit(Pid, Reason)
。
我正在尝试了解 erlang 主管。我有一个简单的 printer process
,每 3 秒打印一次 hello。我还有一个主管,如果发生任何异常,必须重新启动 printer process
。
这是我的代码:
test.erl:
-module(test).
-export([start_link/0]).
start_link() ->
io:format("started~n"),
Pid = spawn_link(fun() -> loop() end),
{ok, Pid}.
loop() ->
timer:sleep(3000),
io:format("hello~n"),
loop().
test_sup.erl:
-module(test_sup).
-behaviour(supervisor).
-export([start_link/0]).
-export([init/1]).
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
init(_Args) ->
SupFlags = #{strategy => one_for_one, intensity => 1, period => 5},
ChildSpecs = [#{id => test,
start => {test, start_link, []},
restart => permanent,
shutdown => brutal_kill,
type => worker,
modules => [test]}],
{ok, {SupFlags, ChildSpecs}}.
现在我 运行 这个程序并使用 test_sup:start_link().
命令启动主管,几秒钟后,我引发了一个异常。为什么supervisor不重启printer process
?
这是 shell 输出:
1> test_sup:start_link().
started
{ok,<0.36.0>}
hello
hello
hello
hello
2> erlang:error(err).
=ERROR REPORT==== 13-Dec-2016::00:57:10 ===
** Generic server test_sup terminating
** Last message in was {'EXIT',<0.34.0>,
{err,
[{erl_eval,do_apply,6,
[{file,"erl_eval.erl"},{line,674}]},
{shell,exprs,7,
[{file,"shell.erl"},{line,686}]},
{shell,eval_exprs,7,
[{file,"shell.erl"},{line,641}]},
{shell,eval_loop,3,
[{file,"shell.erl"},{line,626}]}]}}
** When Server state == {state,
{local,test_sup},
one_for_one,
[{child,<0.37.0>,test,
{test,start_link,[]},
permanent,brutal_kill,worker,
[test]}],
undefined,1,5,[],0,test_sup,[]}
** Reason for termination ==
** {err,[{erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,674}]},
{shell,exprs,7,[{file,"shell.erl"},{line,686}]},
{shell,eval_exprs,7,[{file,"shell.erl"},{line,641}]},
{shell,eval_loop,3,[{file,"shell.erl"},{line,626}]}]}
** exception error: err
当您执行 erlang:error(err).
时,您正在终止调用进程,您的 shell.
因为你已经用start_link启动了supervisor,它也被kill掉了,loop也一样。
shell自动重启(多亏了一些监督者),但是没有人重启你的测试监督者,这无法重启循环。
要进行此测试,您应该这样做:
在模块测试中:
start_link() ->
Pid = spawn_link(fun() -> loop() end),
io:format("started ~p~n",[Pid]),
{ok, Pid}.
你会得到一个提示:
started <0,xx,0>
其中<0,xx,0>
是循环pid,在shell中可以调用
exit(pid(0,xx,0), err).
仅终止循环。
这是您使用文件创建的架构:
test_sup (supervisor)
^
|
v
test (worker)
然后您通过在 shell 中调用 start_link()
来启动您的主管。这将创建另一个双向 link:
shell
^
|
v
test_sup (supervisor)
^
|
v
test (worker)
双向link,如果一方死亡,另一方也被杀死。
当您 运行 erlang:error
时,您会导致 shell 出错!
你的 shell 被 link 发送给你的主管,所以 Erlang 杀死主管作为回应。通过连锁反应,你的工人也被杀了。
我认为您打算将错误情况发送给您的工作人员而不是 shell:
- 确定您的工人的 PID:
supervisor:which_children
- 在工人的 Pid 上调用
erlang:exit(Pid, Reason)
。