[erlang-questions] A question on EINVAL in active-mode TCP
Magnus Ottenklinger
magnus.ottenklinger@REDACTED
Thu Jun 30 10:58:11 CEST 2016
Hi List.
We stumbled over a peculiarity in the usage of ports in a TCP connection (active mode). Specifically, we encountered `einval` when writing to a socket which was closed just before. Our expectation was that the resulting error should be `{error,closed}`. The following module reproduces this on my machine (OTP 19.0). I ran the test module with `erlc test.erl && erl -s test run -noshell` as well as with `erl -smp disable +A 0 -s test run -noshell`. Both executions triggered `einval`.
-module(test).
-export([run/0]).
run() -> run(0).
run(I) -> io:format("Run ~p~n", [I]), run1(), run(I+1).
run1() ->
{ok,LSock} = gen_tcp:listen(0, []),
{ok,Port} = inet:port(LSock),
spawn_link(
fun() ->
{ok,Sock} = gen_tcp:accept(LSock),
gen_tcp:close(LSock),
gen_tcp:close(Sock)
end),
{ok,Sock} = gen_tcp:connect("localhost", Port, []),
case gen_tcp:send(Sock, "Hello") of
ok -> ok;
{error,closed} -> ok
end,
gen_tcp:close(Sock).
Here, the execution stops after about 3800 runs with `{case_clause,{error,einval}}`. It seems weird that the test module usually encounters `{error,closed}`, and only after some time hits `{error,einval}`. This hints at a race condition, but I am unsure if this is instead expected behaviour.
So, finally to the actual question: Should we expect `einval` on active-mode TCP and interpret it as `closed`? Or is this a fixable race condition?
Cheers, Magnus
More information about the erlang-questions
mailing list