为啥我的 Erlang 应用程序崩溃了?

Posted

技术标签:

【中文标题】为啥我的 Erlang 应用程序崩溃了?【英文标题】:Why is my Erlang application crashing?为什么我的 Erlang 应用程序崩溃了? 【发布时间】:2014-09-20 12:28:21 【问题描述】:

我正在构建一个简单的 erlang 应用程序,并且对环境非常陌生,所以我无法理解我遇到的一些错误。我不确定我的问题的根源是什么,所以如果我没有发布任何相关的内容,请告诉我:

我正在运行的模块的来源:

  -module(basilisk_server).
  -author("Oak").

  -export([start_link/2,start/0,start/1,start/2, stop/1]).
  -behaviour(application).
  -record(options,
    port = 6890,
    server_opts = []
  ).
  -define(LocalIP,"192.168.64.128").
  start()->
    start([]).
  start(Args)->
    #optionsport = Port, server_opts = ServerOpts  = parse_args(Args),
    spawn(
      fun() ->
        start_link(Port, ServerOpts),
        receive after infinity -> ok end
      end)
  .
  start(_StartType, Args) ->
    start(Args).

  parse_args(Args) -> parse_args(Args, #options).
  parse_args([], Opts) -> Opts;
  parse_args([Head | Rest], Opts) ->
    NewOpts =
      case catch list_to_integer(Head) of
        Port when is_integer(Port) ->
          Opts#optionsport = Port;
        _Else ->
          case Head of
            "framed" ->
              Opts#optionsserver_opts = [framed, true | Opts#options.server_opts];
            "" ->
              Opts;
            _Else ->
              erlang:error(bad_arg, Head)
          end
      end,
    parse_args(Rest, NewOpts)
  .
  stop(_State) ->
    ok.

  start_link(Port, ServerOpts) ->
    io:format("Starting server on port ~p with args: ~p~n",[Port,ServerOpts]),

    Services =
      [
        "AuthenticationService",authenticationService_thrift,
        "UserRegistrationService",userRegistrationService_thrift
      ]
    ,
    ok, _ = thrift_socket_server:start([
      ip, ?LocalIP,

      port, Port,
      name, ?MODULE,
      service, Services,
      handler,[
        "error_handler",  thrift_error_handler,
        "AuthenticationService",authentication_service,
        "UserRegistrationService",user_registration_service
      ],
      socket_opts, [recv_timeout, infinity]
    ]++
    ServerOpts).

我运行application:start(basilisk_server). 并按以下顺序获取这些消息:

   error,bad_return,basilisk_server,start,[normal,[]],
                      <0.38.0>

  =INFO REPORT==== 29-Jul-2014::03:11:06 ===
      application: basilisk_server
      exited: bad_return,basilisk_server,start,[normal,[]],<0.38.0>
      type: temporary

  =ERROR REPORT==== 29-Jul-2014::03:11:06 ===
  Error in process <0.38.0> with exit value: terminated,[io,format,
 [<0.36.0>,"Starting server on port ~p with args: ~p~n",[6890,[]]],[],
 basilisk_server,start_link,2,[file,"src/basilisk_server.erl",line,55], 
 basilisk_server,'-start/1-fun-0-',2,[file,"src/basilisk_serve... 

我遇到的主要问题是确定错误的实际来源。我的印象是io:format 是短时间内的问题,但我相信这是一个“红鲱鱼”,而 bad_result 是我问题的根源。我以几乎相同的状态运行程序并且它正在运行,但突然开始出现此错误。我回滚了大部分更改,但它并没有停止。我还尝试重新启动,以防后台进程出现问题。

【问题讨论】:

在给出有效答案以否决这个问题后,这不是一个......有趣的......时间长度吗? 【参考方案1】:

您正在使用application:start,它希望您的模块遵守application 行为。

也就是说:它会调用foo:start/2,告诉你你的应用程序正在启动。您应该返回ok, Pid。这记录在 OTP 设计原则的“应用程序”chapter 中。

但是,您的 start 函数会立即调用 spawn,并使用其结果。由于spawn 返回Pid,而不是ok, Pidapplication:start 抱怨预期结果不匹配。

这就是你看到bad_return的原因:

error,bad_return,basilisk_server,start,[normal,[]],
                  <0.38.0>

这告诉你你有一个error,类型为bad_return。它发生在调用basilisk_server:start(normal, []) 时,它的返回值为&lt;0.38.0&gt;(一个pid)。

哦,另一个错误是因为你使用了start_link,这意味着你的两个进程是链接的。当一个人死了,另一个人就会被杀死。这就是您通过terminated 看到的内容。在这种情况下,它恰好在io:format的中间被杀死;它可能会在其他运行中被杀死之前更进一步。

此外,假设应用程序启动一个根主管(这就是返回的 pid 的用途)。

此时,您不需要application 行为。事实上,我根本不相信您需要大部分代码。只需致电thrift_socket_server:start 即可完成。它将继续在后台运行。

【讨论】:

我正在寻找 start 的预期结果但找不到它,谢谢(我翻阅了我这里的书,它没有提到它,我读了那个例子但推断“预计返回最高主管的pid”意味着简单地返回一个pid)。此外,我删除了我发布的示例的大部分代码,行为比这里看起来的要多。感谢您的澄清。

以上是关于为啥我的 Erlang 应用程序崩溃了?的主要内容,如果未能解决你的问题,请参考以下文章

我的程序崩溃了,我不知道为啥

为啥我的相机应用程序崩溃了?

为啥我的签名 apk 崩溃了?

为啥我的 unwind segue 会使我的应用程序崩溃?

为啥我的应用程序在模拟器中崩溃?

当我删除核心数据实体的最后一条记录时,为啥我的应用程序崩溃了?