1

编辑:下面。

为什么我的受监督的 gen_server 这么快就关闭了?

我将给出这些组织名称以更清楚地说明我希望在我的应用程序中使用的命令链:首先我从“assembly_line_worker”开始,然后将“marketing_specialist”添加到我的监督树中......

ceo_supervisor.erl

-module(ceo_supervisor).
-behaviour(supervisor).

-export([start_link/1]).
-export([init/1]).

start_link(State) ->
     supervisor:start_link({local,?MODULE}, ?MODULE, [State]).

init([Args]) ->
     RestartStrategy = {one_for_one, 10, 60},
     ChildSpec= {assembly_line_worker_supervisor,
          {assembly_line_worker_supervisor, start_link, [Args]},
          permanent, infinity, supervisor, [assembly_line_worker_supervisor]},
     {ok, {RestartStrategy, [ChildSpec]}}.    

assembly_line_worker_supervisor.erl

-module(assembly_line_worker_supervisor).
-behaviour(supervisor).

-export([start_link/1]).
-export([init/1]). %% Internal

start_link(State) ->
    supervisor:start_link({local, ?MODULE}, ?MODULE, [State]).

init([Args]) ->
    RestartStrategy = {one_for_one, 10, 60},
    ChildSpec = {assembly_line_worker, {assembly_line_worker, start_link, [Args]}, permanent,     
        infinity, worker, [assembly_line_worker]},
    {ok, {RestartStrategy, [ChildSpec]}}.

装配线工人.erl

-module(assembly_line_worker).
...

init([State]) ->
   process_flag(trap_exit, true),
   {ok, State}.

start_link(State) ->
    gen_server:start_link({global, ?MODULE}, ?MODULE, [State], []).

handle_cast(...,State} ->
    io:format("We're getting this message.~n",[]),
    {noreply, State};
...

正在发生的事情是装配线工人做了一些工作,比如在调用 ceo_supervisor:start_link(#innovative_ideas{}) 命令后接收到几条消息,然后它就关闭了。知道为什么吗?我知道 gen_server 正在接收一些消息,因为它 io:format 将它们发送到控制台。

谢谢!


编辑:我通过 erlsrv.exe 在 Windows 上托管它,我发现当我通过如下函数启动程序时:

start() ->
    ceo_supervisor:start_link(#innovative_ideas{}),
    assembly_line_worker:ask_for_more_pay(), %% Prints out "I want more $$$" as expected,
    ok.

...此功能立即退出会导致我的主管/gen_servers 关闭。我希望这是因为所有这些都通过监督链接到原始调用过程,所以当它退出时,孩子们也应该这样做。

所以我想一个更好的问题是,我怎样才能让我的主管在完成所有启动配置后继续运行?除了将所有这些包装在应用程序中之外,还有其他选择吗?(听起来还不错……)

感谢您的探索性问题!我通过这种方式了解了更多关于主管的信息。

蝙蝠侠

4

2 回答 2

2

要获得有关正在发生的事情的更多信息,请在启动主管之前启动 sasl:application:start(sasl)。

另一种调试方法是从您的 erlang shell 启动工作程序,发送导致服务器崩溃的消息序列。顺便说一句:你确定你需要 2 级主管吗?

于 2012-10-11T09:13:32.213 回答
2

一些即时评论:

ceo_supervisor:init/1您的主管子规范中应声明transient而不是permanent.

运行erl -boot start_sasl,以便在出现问题时获得错误日志,并且可以获得崩溃程序的崩溃报告。

如果你在 shell 中运行它并且你犯了任何错误,那么你的树将被强行杀死。这是因为您链接到 shell 并且 shell 在错误时崩溃。所以你正在拖下你的树。尝试类似:

 Pid = spawn(fun() -> my_app:start() end).

所以你把它分开了。您可以通过向 发送退出消息来终止应用程序Pid

于 2012-10-13T11:23:00.183 回答