首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >erlang otp童工

erlang otp童工
EN

Stack Overflow用户
提问于 2013-10-22 23:27:52
回答 2查看 1.1K关注 0票数 1

我正试图让OTP主管启动子工作人员,这将(最终)连接到远程服务器。我使用Rebar创建了一个模板测试应用程序,并试图让主管在'foo‘模块中启动函数'hi’。它编译OK并运行:

代码语言:javascript
复制
Eshell V5.8.5  (abort with ^G)
1> test_app:start(1,1).
{ok,<0.34.0>}

但是,当我试图启动工人时,它会变成梨形,这是错误的结果:

代码语言:javascript
复制
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

代码语言:javascript
复制
-module(test_app).
-behaviour(application).net 
-export([start/2, stop/1]).

start(_StartType, _StartArgs) ->
    test_sup:start_link().

stop(_State) ->
    ok.

Test_sup.erl:

代码语言:javascript
复制
-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:

代码语言:javascript
复制
-module(foo).
-export([hi/0]).
hi()->
io:format("worker ~n").
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 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。下面的代码打印错误,但似乎工作正常。

代码语言:javascript
复制
-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,但我读到它应该用于必须在死前完成任务的进程。

票数 0
EN

Stack Overflow用户

发布于 2013-10-22 23:48:29

使用宏调用?CHILD(foo, worker)检查子规范,同时尝试使用宏调用?CHILD(foo, permanent)启动子宏。CHILD宏的第二个参数是进程类型,它应该是workersupervisor。所以第一个宏调用是正确的。值permanent是重新启动类型的值,您已经将其设置为permanent,因此第二个调用是错误的,您将得到一个badarg错误。

注意:库函数也经常生成badarg错误,而不仅仅是内建函数。并不总是很清楚为什么是个坏蛋。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19530109

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档