Use outside of ephemeral port range to listen on

When there is TCP_WAIT connection whose local part has
port to be listened, listen (bind) will fail by eaddrinuse
_on Linux_ (won't on Mac OS X).
This commit also adds some logs and pattern matches.

Reference
- Ephemeral port - Wikipedia, the free encyclopedia
  https://en.wikipedia.org/wiki/Ephemeral_port

  "Many Linux kernels use the port range 32768 to 61000.[note 2]
  FreeBSD has used the IANA port range since release 4.6. Previous
  versions, including the Berkeley Software Distribution (BSD), use
  ports 1024 to 5000 as ephemeral ports.[2]"

- Demostration of collision between already-closed ephemeral port
  and listen port on Linux (Mac OS X allows)
  https://gist.github.com/shino/36ae1e01608366d52236
This commit is contained in:
Shunichi Shinohara 2015-12-09 18:04:50 +09:00
parent ade4430d30
commit 2e2d282afc
2 changed files with 18 additions and 13 deletions

View file

@ -113,17 +113,22 @@ handle_info({tcp_closed, Socket}=_Info, #state{socket=Socket}=S) ->
lager:debug("~s:handle_info: ~w", [?MODULE, _Info]),
transport_closed(Socket, S);
handle_info({tcp_error, Socket, Reason}=_Info, #state{socket=Socket}=S) ->
lager:debug("~s:handle_info: ~w", [?MODULE, _Info]),
lager:warning("~s:handle_info (socket=~w) tcp_error: ~w", [?MODULE, Socket, Reason]),
transport_error(Socket, Reason, S);
handle_info(_Info, S) ->
lager:warning("~s:handle_info UNKNOWN message: ~w", [?MODULE, _Info]),
{noreply, S}.
terminate(_Reason, #state{socket=undefined}=_S) ->
lager:debug("~s:terminate: ~w", [?MODULE, _Reason]),
terminate(normal, #state{socket=undefined}=_S) ->
ok;
terminate(_Reason, #state{socket=Socket}=_S) ->
lager:debug("~s:terminate: ~w", [?MODULE, _Reason]),
terminate(Reason, #state{socket=undefined}=_S) ->
lager:warning("~s:terminate (socket=undefined): ~w", [?MODULE, Reason]),
ok;
terminate(normal, #state{socket=Socket}=_S) ->
(catch gen_tcp:close(Socket)),
ok;
terminate(Reason, #state{socket=Socket}=_S) ->
lager:warning("~s:terminate (socket=Socket): ~w", [?MODULE, Reason]),
(catch gen_tcp:close(Socket)),
ok.

View file

@ -34,13 +34,13 @@
flu_smoke_test() ->
Host = "localhost",
TcpPort = 32957,
TcpPort = 12957,
DataDir = "./data",
Prefix = <<"prefix!">>,
BadPrefix = BadFile = "no/good",
W_props = [{initial_wedged, false}],
{_, _, _} = machi_test_util:start_flu_package(smoke_flu, TcpPort, DataDir, W_props),
try
_ = machi_test_util:start_flu_package(smoke_flu, TcpPort, DataDir, W_props),
Msg = "Hello, world!",
Msg = ?FLU_C:echo(Host, TcpPort, Msg),
{error, bad_arg} = ?FLU_C:checksum_list(Host, TcpPort,
@ -142,10 +142,10 @@ flu_smoke_test() ->
flu_projection_smoke_test() ->
Host = "localhost",
TcpPort = 32959,
TcpPort = 12959,
DataDir = "./data.projst",
{_,_,_} = machi_test_util:start_flu_package(projection_test_flu, TcpPort, DataDir),
try
machi_test_util:start_flu_package(projection_test_flu, TcpPort, DataDir),
[ok = flu_projection_common(Host, TcpPort, T) ||
T <- [public, private] ]
%% , {ok, {false, EpochID1}} = ?FLU_C:wedge_status(Host, TcpPort),
@ -179,11 +179,11 @@ flu_projection_common(Host, TcpPort, T) ->
bad_checksum_test() ->
Host = "localhost",
TcpPort = 32960,
TcpPort = 12960,
DataDir = "./data.bct",
Opts = [{initial_wedged, false}],
{_,_,_} = machi_test_util:start_flu_package(projection_test_flu, TcpPort, DataDir, Opts),
try
machi_test_util:start_flu_package(projection_test_flu, TcpPort, DataDir, Opts),
Prefix = <<"some prefix">>,
Chunk1 = <<"yo yo yo">>,
Chunk1_badcs = {<<?CSUM_TAG_CLIENT_SHA:8, 0:(8*20)>>, Chunk1},
@ -197,11 +197,11 @@ bad_checksum_test() ->
witness_test() ->
Host = "localhost",
TcpPort = 32961,
TcpPort = 12961,
DataDir = "./data.witness",
Opts = [{initial_wedged, false}, {witness_mode, true}],
{_,_,_} = machi_test_util:start_flu_package(projection_test_flu, TcpPort, DataDir, Opts),
try
machi_test_util:start_flu_package(projection_test_flu, TcpPort, DataDir, Opts),
Prefix = <<"some prefix">>,
Chunk1 = <<"yo yo yo">>,