Module 为什么我的主管在启动undef儿童时失败?
我正在尝试运行一个Module 为什么我的主管在启动undef儿童时失败?,module,erlang,erlang-supervisor,Module,Erlang,Erlang Supervisor,我正在尝试运行一个simple\u one\u for\u one supervisor,其中supervisor和worker被放置在不同的模块中,使用supervisor时,我不断收到以下错误:启动子项: >A=sup:start_link(). >B=supervisor:start_child(A,[]). {error,{'EXIT',{undef,[{worker,start_link,[],[]}, {supervisor,
simple\u one\u for\u one supervisor
,其中supervisor
和worker
被放置在不同的模块中,使用supervisor时,我不断收到以下错误:启动子项
:
>A=sup:start_link().
>B=supervisor:start_child(A,[]).
{error,{'EXIT',{undef,[{worker,start_link,[],[]},
{supervisor,do_start_child_i,3,
[{file,"supervisor.erl"},{line,379}]},
{supervisor,handle_call,3,
[{file,"supervisor.erl"},{line,404}]},
{gen_server,try_handle_call,4,
[{file,"gen_server.erl"},{line,661}]},
{gen_server,handle_msg,6,
[{file,"gen_server.erl"},{line,690}]},
{proc_lib,init_p_do_apply,3,
[{file,"proc_lib.erl"},{line,249}]}]}}}
主管
-module(sup).
-behaviour(supervisor).
-compile([export_all]).
start_link()->
{ok,Pid}=supervisor:start_link(?MODULE,[]),
io:format("sugi pl"),
Pid.
init(_Args) ->
RestartStrategy = {simple_one_for_one, 10, 60},
ChildSpec = {
worker,
{worker, start_link, []}, //tried adding here a parameter in the A
permanent,
brutal_kill,
worker,
[sup]
},
{ok, {RestartStrategy,[ChildSpec]}}.
-module(worker).
-compile(export_all).
start_link([Arg])-> //tried both [Arg] and Arg
{ok,Pid}=spawn_link(?MODULE,init,[]),
Pid.
init([Time])->
receive->
{From,Msg}->From !{Time,Msg},
init(Time)
end.
-module(sup).
-behaviour(supervisor).
-compile([export_all]).
start_link()->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
init(_Args) ->
RestartStrategy = {simple_one_for_one, 10, 60},
ChildSpec = {
worker,
{worker, start_link, []},
permanent,
brutal_kill,
worker,
[worker]
},
{ok, {RestartStrategy,[ChildSpec]}}.
-module(worker).
-compile(export_all).
start_link()->
Pid = spawn_link(?MODULE,init,[os:timestamp()]),
{ok, Pid}.
init(Time) ->
receive
{From,Msg} ->
From ! {Time,Msg},
init(Time)
end.
工人
-module(sup).
-behaviour(supervisor).
-compile([export_all]).
start_link()->
{ok,Pid}=supervisor:start_link(?MODULE,[]),
io:format("sugi pl"),
Pid.
init(_Args) ->
RestartStrategy = {simple_one_for_one, 10, 60},
ChildSpec = {
worker,
{worker, start_link, []}, //tried adding here a parameter in the A
permanent,
brutal_kill,
worker,
[sup]
},
{ok, {RestartStrategy,[ChildSpec]}}.
-module(worker).
-compile(export_all).
start_link([Arg])-> //tried both [Arg] and Arg
{ok,Pid}=spawn_link(?MODULE,init,[]),
Pid.
init([Time])->
receive->
{From,Msg}->From !{Time,Msg},
init(Time)
end.
-module(sup).
-behaviour(supervisor).
-compile([export_all]).
start_link()->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
init(_Args) ->
RestartStrategy = {simple_one_for_one, 10, 60},
ChildSpec = {
worker,
{worker, start_link, []},
permanent,
brutal_kill,
worker,
[worker]
},
{ok, {RestartStrategy,[ChildSpec]}}.
-module(worker).
-compile(export_all).
start_link()->
Pid = spawn_link(?MODULE,init,[os:timestamp()]),
{ok, Pid}.
init(Time) ->
receive
{From,Msg} ->
From ! {Time,Msg},
init(Time)
end.
命令
>c("[somepath]/sup.erl"),A=sup:start_link(),B=supervisor:start_child(A,[]).
我可以清楚地看到问题是在尝试添加子项时。不知何故,init
函数调用不正确,但我不明白原因。(Badmatch)我已尝试在
ChildSpec
的MFA
的a
中添加一个参数,但没有效果您的代码存在许多问题
的返回值错误;返回的是Pid而不是sup:start\u link/0
{ok,Pid}
- 虽然这并不是真的不正确,但您使用的是
,它没有注册supervisor名称。有这个名字很方便,所以最好使用supervisor:start\u link/2
:supervisor:start\u link/3
这将模块名称与其进程id相关联,允许您在shell命令中使用进程名称,而不是使用pid变量supervisor:start_link({local, ?MODULE}, ?MODULE, []),
- 您有一个
调用io:format/2
,可能是为了调试。一种更好的调试方法是在启动sup:start\u link/0
监控程序后,从shell调用sup
。通过指定sys:trace(sup,true)
而不是false
作为第二个参数,也可以从shell中关闭它true
sup:start\u link/0
:
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
让我们重新编译,启动主管,然后编译worker
(修复其语法错误后),然后在尝试启动子级时跟踪主管:
1> c(sup).
sup.erl:3: Warning: export_all flag enabled - all functions will be exported
{ok,sup}
2> sup:start_link().
{ok,<0.94.0>}
3> sys:trace(sup, true).
ok
4> c(worker).
worker.erl:2: Warning: export_all flag enabled - all functions will be exported
worker.erl:5: Warning: variable 'Arg' is unused
{ok,worker}
5> supervisor:start_child(sup, []).
*DBG* sup got call {start_child,[]} from <0.81.0>
*DBG* sup sent {error,
{'EXIT',
{undef,
[{worker,start_link,[],[]},
{supervisor,do_start_child_i,3,
[{file,"supervisor.erl"},{line,379}]},
...
我们通过supervisor:start\u child(sup,[])
启动了这个孩子。对于simple\u one\u For_one
子函数,发送到其start函数的参数由子规范中的参数列表和调用supervisor:start\u child/2
中指定的参数组成;在本例中,这相当于[]+[]
,与[]]
相同,表示没有参数。让我们将worker:start\u link/1
函数改为worker:start\u link/0
,重新编译它,然后重试:
6> c(worker).
worker.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,worker}
7> supervisor:start_child(sup, []).
*DBG* sup got call {start_child,[]} from <0.81.0>
*DBG* sup sent {error,
{'EXIT',
{{badmatch,<0.94.0>},
[{worker,start_link,0,[{file,"worker.erl"},{line,6}]},
...
8> c(worker).
worker.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,worker}
9> supervisor:start_child(sup, []).
*DBG* sup got call {start_child,[]} from <0.81.0>
*DBG* sup sent {ok,<0.106.0>} to <0.81.0>, new state {state,
{local,sup},
simple_one_for_one,
{[worker],
#{worker =>
{child,undefined,
worker,
{worker,
start_link,[]},
permanent,
brutal_kill,worker,
[sup]}}},
{maps,
#{<0.106.0> => []}},
10,60,[],0,sup,[]}
*DBG* sup got {'EXIT',<0.106.0>,{undef,[{worker,init,[],[]}]}}
10> sup:start_link().
{ok,<0.119.0>}
11> sys:trace(sup, true).
ok
12> c(worker).
worker.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,worker}
13> {ok, Child} = supervisor:start_child(sup, []).
*DBG* sup got call {start_child,[]} from <0.118.0>
*DBG* sup sent {ok,<0.127.0>} to <0.118.0>, new state {state,
{local,sup},
simple_one_for_one,
{[worker],
#{worker =>
{child,undefined,
worker,
{worker,
start_link,[]},
permanent,
brutal_kill,
worker,
[sup]}}},
{maps,
#{<0.127.0> => []}},
10,60,[],0,sup,[]}
{ok,<0.127.0>}
然后让我们重新编译并重试:
6> c(worker).
worker.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,worker}
7> supervisor:start_child(sup, []).
*DBG* sup got call {start_child,[]} from <0.81.0>
*DBG* sup sent {error,
{'EXIT',
{{badmatch,<0.94.0>},
[{worker,start_link,0,[{file,"worker.erl"},{line,6}]},
...
8> c(worker).
worker.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,worker}
9> supervisor:start_child(sup, []).
*DBG* sup got call {start_child,[]} from <0.81.0>
*DBG* sup sent {ok,<0.106.0>} to <0.81.0>, new state {state,
{local,sup},
simple_one_for_one,
{[worker],
#{worker =>
{child,undefined,
worker,
{worker,
start_link,[]},
permanent,
brutal_kill,worker,
[sup]}}},
{maps,
#{<0.106.0> => []}},
10,60,[],0,sup,[]}
*DBG* sup got {'EXIT',<0.106.0>,{undef,[{worker,init,[],[]}]}}
10> sup:start_link().
{ok,<0.119.0>}
11> sys:trace(sup, true).
ok
12> c(worker).
worker.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,worker}
13> {ok, Child} = supervisor:start_child(sup, []).
*DBG* sup got call {start_child,[]} from <0.118.0>
*DBG* sup sent {ok,<0.127.0>} to <0.118.0>, new state {state,
{local,sup},
simple_one_for_one,
{[worker],
#{worker =>
{child,undefined,
worker,
{worker,
start_link,[]},
permanent,
brutal_kill,
worker,
[sup]}}},
{maps,
#{<0.127.0> => []}},
10,60,[],0,sup,[]}
{ok,<0.127.0>}
因为这是一个硬错误,它每次都会立即失败,并且在60秒或更短的时间内重新启动10次失败后,管理器就会死亡,就像它应该:
=SUPERVISOR REPORT==== 20-Apr-2020::10:43:43.557307 ===
supervisor: {local,sup}
errorContext: shutdown
reason: reached_max_restart_intensity
offender: [{pid,<0.117.0>},
{id,worker},
{mfargs,{worker,start_link,[]}},
{restart_type,permanent},
{shutdown,brutal_kill},
{child_type,worker}]
** exception error: shutdown
让我们也修复init/1
以直接获取参数,而不是在列表中:
init(Time) ->
receive
{From,Msg} ->
From ! {Time,Msg},
init(Time)
end.
让我们重新启动主管,重新编译工作程序
,然后重试:
6> c(worker).
worker.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,worker}
7> supervisor:start_child(sup, []).
*DBG* sup got call {start_child,[]} from <0.81.0>
*DBG* sup sent {error,
{'EXIT',
{{badmatch,<0.94.0>},
[{worker,start_link,0,[{file,"worker.erl"},{line,6}]},
...
8> c(worker).
worker.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,worker}
9> supervisor:start_child(sup, []).
*DBG* sup got call {start_child,[]} from <0.81.0>
*DBG* sup sent {ok,<0.106.0>} to <0.81.0>, new state {state,
{local,sup},
simple_one_for_one,
{[worker],
#{worker =>
{child,undefined,
worker,
{worker,
start_link,[]},
permanent,
brutal_kill,worker,
[sup]}}},
{maps,
#{<0.106.0> => []}},
10,60,[],0,sup,[]}
*DBG* sup got {'EXIT',<0.106.0>,{undef,[{worker,init,[],[]}]}}
10> sup:start_link().
{ok,<0.119.0>}
11> sys:trace(sup, true).
ok
12> c(worker).
worker.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,worker}
13> {ok, Child} = supervisor:start_child(sup, []).
*DBG* sup got call {start_child,[]} from <0.118.0>
*DBG* sup sent {ok,<0.127.0>} to <0.118.0>, new state {state,
{local,sup},
simple_one_for_one,
{[worker],
#{worker =>
{child,undefined,
worker,
{worker,
start_link,[]},
permanent,
brutal_kill,
worker,
[sup]}}},
{maps,
#{<0.127.0> => []}},
10,60,[],0,sup,[]}
{ok,<0.127.0>}
正如我们预期的那样,它有一个工人。最后,让我们向worker发送一条消息,看看它是否按预期响应:
15> Child ! {self(), "are you there?"}.
{<0.118.0>,"are you there?"}
16> flush().
Shell got {{1587,394860,258120},"are you there?"}
ok
工人
-module(sup).
-behaviour(supervisor).
-compile([export_all]).
start_link()->
{ok,Pid}=supervisor:start_link(?MODULE,[]),
io:format("sugi pl"),
Pid.
init(_Args) ->
RestartStrategy = {simple_one_for_one, 10, 60},
ChildSpec = {
worker,
{worker, start_link, []}, //tried adding here a parameter in the A
permanent,
brutal_kill,
worker,
[sup]
},
{ok, {RestartStrategy,[ChildSpec]}}.
-module(worker).
-compile(export_all).
start_link([Arg])-> //tried both [Arg] and Arg
{ok,Pid}=spawn_link(?MODULE,init,[]),
Pid.
init([Time])->
receive->
{From,Msg}->From !{Time,Msg},
init(Time)
end.
-module(sup).
-behaviour(supervisor).
-compile([export_all]).
start_link()->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
init(_Args) ->
RestartStrategy = {simple_one_for_one, 10, 60},
ChildSpec = {
worker,
{worker, start_link, []},
permanent,
brutal_kill,
worker,
[worker]
},
{ok, {RestartStrategy,[ChildSpec]}}.
-module(worker).
-compile(export_all).
start_link()->
Pid = spawn_link(?MODULE,init,[os:timestamp()]),
{ok, Pid}.
init(Time) ->
receive
{From,Msg} ->
From ! {Time,Msg},
init(Time)
end.
除了已经发布的优秀答案之外,我想补充几点来解释问题中观察到的行为 childspec中的开始值是一个元组
{Mod,Fun,ArgsList}
,子进程可以通过调用主管:开始\u子进程(主管,列表)
生成。主管通过调用erlang:apply(Mod,Fun,List++ArgsList)
启动子进程
在这种情况下,开始值是{worker,start\u link,[]}
,子项是通过调用主管:start\u child(A,[])
生成的。主管试图调用erlang:apply(worker,start\u link,[])
。这意味着主管希望在worker
模块中定义worker:start\u link/0
。但是worker
模块定义了worker:start\u link/1
。因此出现undef
错误
给出了函数定义
start_link([Arg]) ->
%% do stuff
最好是生成子进程
- 让子规范中的起始值为
{worker,start\u link,[]}
- 呼叫
supervisor:start_child(A,[[Value]])
start_link(Arg) ->
%% so stuff
并调用
supervisor:start_child(A,[Value])
您确定编译并加载了worker
吗?我正在erlang shell中运行我上面编写的命令。如果sup
模块使用worker
模块,是否需要编译它?它们是否都将被编译?unde,[{worker,start\u link,[
表示worker:start\u link/0不存在,但worker仅定义start\u link/1。这可能是因为您的模块不同步。请确保sup和worker对worker:start\u link使用相同的arity,并在重试之前重新编译这两个模块。