【问题标题】:Added supervisor(s) for a gen_server, shutdown immediately?为 gen_server 添加了主管,立即关闭?
【发布时间】:2012-10-01 11:40:50
【问题描述】:

编辑:下面。

为什么我的受监管 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]}}.

assembly_line_worker.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 关闭。我希望这是因为所有这些都通过监督链接到原始调用过程,所以当它退出时,孩子也应该这样做。

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

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

蝙蝠侠

【问题讨论】:

  • 你能提供更多你的 asembly_line_worker.erl 吗?如果此模块在 60 秒内崩溃超过 10 次,则不会再次重新启动。我猜是什么原因导致它超过了最大重启限制,但我需要查看更多代码。
  • 它有几百行长,但我知道我可以在没有主管的情况下启动它,而且它不会崩溃/抛出异常。看看会有什么帮助?
  • 能否举个例子,说明在启动主管时如何调用函数?我想知道您的 childspecs 和 init 函数中的所有列表是否匹配。不幸的是,文档使用"Args" 来表示一个真正必要的参数列表和一个参数数据块。
  • 添加了更多信息。是的,我从来没有意识到在文档中,我认为它应该改为 ArgsList

标签: erlang erlang-otp erlang-supervisor gen-server


【解决方案1】:

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

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

【讨论】:

  • 最终当我添加“marketing_specialist_sup”时,我想我想让这两个主管都受到高层的监督?另外,我不确定我的服务器是否崩溃了,因为我可以在没有主管的情况下正常启动它。
【解决方案2】:

一些直接的cmets:

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 2015-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-18
    • 2019-03-31
    • 1970-01-01
    • 2019-06-16
    相关资源
    最近更新 更多