erlang otp童工

我试图让一个OTP主管启动将会(最终)连接到远程服务器的童工。 我使用钢筋来创建一个模板测试应用程序,我试图让主管在模块'foo'中激发函数'hi'。 它编译好并运行:

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 - 从supervisor模块启动一个孩子

有任何想法吗?

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").

我认为罗伯特的回答是不完整的,在由工作人员取代永久性工作人员之后,您仍然有一个由supervisor:check_childspecs(?CHILD(foo, worker)),返回的错误supervisor:check_childspecs(?CHILD(foo, worker)), ,我不知道为什么。

[编辑]

吟游诗人arg的问题来自... 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终止本身** exception error: shutdown

一般来说,您应该选择permanent结束进程(例如应用程序的主服务器)。 对于通常在他们完成工作后就会死亡的流程,您应该使用temporary流程。 我从来没有使用transient但我读到它应该用于在死前必须完成任务的过程。


当你尝试用宏调用宏来启动孩子时,你使用宏调用?CHILD(foo, worker)来检查childspec ?CHILD(foo, permanent)CHILD宏的第二个参数是过程类型,它应该是workersupervisor 。 所以第一个宏调用是正确的。 permanent值是重启类型的值,您已经设置为permanent ,因此第二次调用是错误的,并且您会收到badarg错误。

注意:库函数badarg生成badarg错误,而不仅仅是内置函数。 为什么它是badarg并不总是显而易见的。

链接地址: http://www.djcxy.com/p/38221.html

上一篇: erlang otp child workers

下一篇: server crashes when started over supervisor