【问题标题】:Erlang: How to trigger ECONNRESET on Linux?Erlang:如何在 Linux 上触发 ECONNRESET?
【发布时间】:2014-05-08 05:42:33
【问题描述】:

我最近在 Mac OS X(不是我的机器!)上使用 Erlang 遇到了类似 heisenbug 的 ECONNRESET。为了简化问题的根源,也为了更好的理解错误本身,我写了下面的模块来触发ECONNRESET。不幸的是,我自己没有 Mac。在我的 Linux (ArchLinux) 上,下面的代码不会因错误匹配 {error,econnreset} 而崩溃,而是会因 {error,closed} 而崩溃。

-module(econnreset).

-export([run/0]).

run() ->
    Pid = spawn_link(fun listen_and_accept/0),
    Pid ! {get_port,self()},
    Port = receive {port,P} -> P end,

    {ok,Socket} = gen_tcp:connect("localhost", Port, [{active,false}]),
    ok = gen_tcp:send(Socket, lists:duplicate(100, $a)),

    %% On the following line, I expected a badmatch w/ {error,econnreset}
    {ok,_} = gen_tcp:recv(Socket, 0, 1000),
    ok = gen_tcp:close(Socket),
    ok.

listen_and_accept() ->
    {ok,LSocket} = gen_tcp:listen(0, [binary,{active,false}]),
    {ok,Port} = inet:port(LSocket),
    receive {get_port,Pid} -> Pid ! {port,Port} end,

    {ok,Socket} = gen_tcp:accept(LSocket),
    {ok,Bin} = gen_tcp:recv(Socket, 1), %=> read only 1 byte to trigger tcp RST
    io:format("Server read ~p~n", [Bin]),
    gen_tcp:close(Socket),
    gen_tcp:close(LSocket).

我只在 Mac OS X 上遇到过 ECONNRESET 而不是在 Linux 上,这归结为两个问题:

  1. 上面的代码甚至能够通过调用recv/2产生ECONNRESET吗?
  2. Mac OS X 和 Linux 在这方面的行为是否不同?

【问题讨论】:

    标签: linux macos sockets erlang


    【解决方案1】:

    可能发生这种情况的一些场景。

    尝试在远程端点已经开始关闭其连接端的套接字上发送新数据可能会导致 ECONNRESET。 (有时它会导致 SIGPIPE 被提升)。

    通常,这很难重现,因为大多数套接字代码通过检测返回 0 的 recv() 调用来获得关闭连接的通知。

    如果远程主机崩溃或断电,也会发生这种情况。一个典型的场景是两台主机之间有一个活动的 TCP 连接。两台主机都没有使用 TCP keep-alives,并且只在彼此之间定期发送/接收数据。目前,假设两台主机都处于空闲状态,并且彼此之间没有任何数据要发送。

    第一台主机 HOST A 暂时断电(即拔掉电源线)并重新启动。另一台主机 HOST B 不知道中断。因此,TCP 状态机认为套接字仍处于连接状态。在某个时候,主机 B 尝试在套接字上发送数据。 IP 数据包最终会到达主机 A。但是主机 A 的 TCP 状态机在重新启动后没有主机 B 的 IP:port 的连接记录。因此,它唯一能做的就是发回一个 RST 通知主机 B 连接已失效。

    我听说过,但我可能是错的...可以通过使用具有零值的 SO_LINGER 将套接字强制进入 CLOSED 状态而不发送 FIN。因此,对方发送的后续数据将导致RST作为响应。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-20
      • 1970-01-01
      • 1970-01-01
      • 2011-08-04
      • 1970-01-01
      • 2012-11-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多