我正试图让OTP主管启动子工作人员,这将(最终)连接到远程服务器。我使用Rebar创建了一个模板测试应用程序,并试图让主管在'foo‘模块中启动函数'hi’。它编译OK并运行:
Eshell V5.8.5 (abort with ^G)
1> test_app:start(1,1).
{ok,<0.34.0>}但是,当我试图启动工人时,它会变成梨形,这是错误的结果:
2> test_sup:start_foo().
{error,{badarg,{foo,{foo,start_link,[]},
permanent,5000,worker,
[foo]}}}这个问题似乎与这个问题相似,但并不相同:Erlang - Starting a child from the supervisor module
有什么想法吗?
test_app.erl
-module(test_app).
-behaviour(application).net
-export([start/2, stop/1]).
start(_StartType, _StartArgs) ->
test_sup:start_link().
stop(_State) ->
ok.Test_sup.erl:
-module(test_sup).
-behaviour(supervisor).
-export([start_link/0]).
-export([init/1, start_foo/0]).
-define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}).
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
init([]) ->
{ok, { {one_for_one, 5, 10}, []} }.
start_foo()->
supervisor:check_childspecs(?CHILD(foo, worker)),
supervisor:start_child(?MODULE, ?CHILD(foo, permanent)). foo.erl:
-module(foo).
-export([hi/0]).
hi()->
io:format("worker ~n").发布于 2013-10-23 04:16:56
我认为罗伯特的回答是不完整的,在用工人代替永久之后,你仍然有一个由supervisor:check_childspecs(?CHILD(foo, worker)),返回的错误,我不知道为什么。
编辑
吟游诗人的问题来自..。badarg :o)
check_childspecs执行一个child_specs列表,正确的语法是supervisor:check_childspecs([?CHILD(foo, worker)]),,然后它就可以正常工作了。下面的代码被更新。
编辑的端
但是您也会得到一个错误,因为监控器将尝试启动foo模块中不存在的函数foo:start_link。下面的代码打印错误,但似乎工作正常。
-module(foo).
-export([hi/0,start_link/0,loop/0]).
start_link() ->
{ok,spawn_link(?MODULE,loop,[])}.
hi()->
io:format("worker ~n").
loop() ->
receive
_ -> ok
end.
-module(test_sup).
-behaviour(supervisor).
-export([start_link/0]).
-export([init/1, start_foo/0]).
-define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}).
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
init([]) ->
{ok, { {one_for_one, 5, 10}, []} }.
start_foo()->
io:format("~p~n",[supervisor:check_childspecs([?CHILD(foo, worker)])]),
supervisor:start_child(?MODULE, ?CHILD(foo, worker)). 编辑
回答大卫的评论
在我的代码中,loop/0根本不循环,在接收块上,进程等待任何消息,一旦收到消息,进程就会终止返回值ok。因此,只要工作进程没有收到任何消息,它就会继续存在,这是很好的,当您与主管进行一些测试时:o)。
相反,hi/0函数只需在控制台上打印“worker”并完成。由于监控程序的重新启动策略是one_for_one,最大重新启动为5,子进程是永久的,监控程序将尝试启动hi进程5次,在控制台上打印五次“worker”,然后它将放弃并以错误消息** exception error: shutdown终止自身。
通常,您应该为永不结束的进程选择permanent (例如,应用程序的主服务器)。对于通常在他们完成任务后就会死的进程,您应该使用temporary。我从未使用过transient,但我读到它应该用于必须在死前完成任务的进程。
发布于 2013-10-22 23:48:29
使用宏调用?CHILD(foo, worker)检查子规范,同时尝试使用宏调用?CHILD(foo, permanent)启动子宏。CHILD宏的第二个参数是进程类型,它应该是worker或supervisor。所以第一个宏调用是正确的。值permanent是重新启动类型的值,您已经将其设置为permanent,因此第二个调用是错误的,您将得到一个badarg错误。
注意:库函数也经常生成badarg错误,而不仅仅是内建函数。并不总是很清楚为什么是个坏蛋。
https://stackoverflow.com/questions/19530109
复制相似问题