[erlang-questions] Erlang socket doesn't receive until the second setopts {active, once}

Jesper Louis Andersen jesper.louis.andersen@REDACTED
Thu Oct 20 00:40:40 CEST 2011

On Wed, Oct 19, 2011 at 23:44, Mediocre Gopher <mediocregopher@REDACTED> wrote:
> process_sock_loop(Sock,Auth) ->
>    try inet:setopts(Sock,[{active,once}]) of
>    ok ->
>        receive

I really don't like the try...catch block there. I am not sure
process_sock_loop is tail recursive with them in because the stack
requires an exception handler frame for each call. Also, I'd recommend
tracing if any other call in the loop is getting hit so you are sure
data is not fluked.

> In trying to debug this I pulled up wireshark. The tcp handshake
> always happens immediately, and when the first packet from the client
> (netcat) is sent it acks immediately, telling me that the tcp stack of
> the kernel isn't the bottleneck.

This is good because then the kernel at least took the data and
buffered it. This means that the error, if there, lies in the Erlang
VM or something above that never receives.

I'd probably do:

enter_loop(Sock, Auth) ->
  ok = inet:setopts(Sock, [{active, once}]),
  loop(Sock, Auth).

loop(Sock, Auth) ->
    {tcp, Sock, Data} ->
      ok = inet:setopts(Sock, [{active, once}]), % We do this as early
as possible so data handling is interleaved
      handle_data(Data), % perhaps you need a continuation here as
data is not framed.
  after 6000 ->
       ok = inet:setopts(Sock, [{active, once}]) % We probably want to warn here
  loop(Sock, Auth).

Note that these are shots in the dark. I have no idea exactly what is
happening, but at least this would let you start off debugging it.
Make tests that acknowledges what you think happens. So test that the
data is not caught and thrown away. Test that it actually hit the
timer and loops again. And so on. Basically get an ACK from each thing
in the system that it does things like you expect it to do.


More information about the erlang-questions mailing list