aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Nilsson <[email protected]>2018-03-06 11:42:28 +0100
committerHans Nilsson <[email protected]>2018-03-07 14:18:57 +0100
commit7a86736c1e2bc0468acd18b1f84c7cbf055befc8 (patch)
tree5e4ea6b379d26dd70a84a413407c358244f5338d
parent249549e8102d68ab086c418fa93494906c4445d0 (diff)
downloadotp-7a86736c1e2bc0468acd18b1f84c7cbf055befc8.tar.gz
otp-7a86736c1e2bc0468acd18b1f84c7cbf055befc8.tar.bz2
otp-7a86736c1e2bc0468acd18b1f84c7cbf055befc8.zip
ssh: Retry and exponentially backoff listener restart
in case of eaddrinuse. This could happen if the acceptor process dies and is restarted immediatly.
-rw-r--r--lib/ssh/src/ssh_acceptor.erl16
1 files changed, 15 insertions, 1 deletions
diff --git a/lib/ssh/src/ssh_acceptor.erl b/lib/ssh/src/ssh_acceptor.erl
index d66a34c58a..27d4242dd4 100644
--- a/lib/ssh/src/ssh_acceptor.erl
+++ b/lib/ssh/src/ssh_acceptor.erl
@@ -86,7 +86,8 @@ acceptor_init(Parent, Port, Address, Opts, AcceptTimeout) ->
acceptor_loop(Callback, Port, Address, Opts, LSock, AcceptTimeout);
{error,_} -> % Not open, a restart
- {ok,NewLSock} = listen(Port, Opts),
+ %% Allow gen_tcp:listen to fail 4 times if eaddrinuse:
+ {ok,NewLSock} = try_listen(Port, Opts, 4),
proc_lib:init_ack(Parent, {ok, self()}),
Opts1 = ?DELETE_INTERNAL_OPT(lsocket, Opts),
{_, Callback, _} = ?GET_OPT(transport, Opts1),
@@ -98,6 +99,19 @@ acceptor_init(Parent, Port, Address, Opts, AcceptTimeout) ->
end.
+try_listen(Port, Opts, NtriesLeft) ->
+ try_listen(Port, Opts, 1, NtriesLeft).
+
+try_listen(Port, Opts, N, Nmax) ->
+ case listen(Port, Opts) of
+ {error,eaddrinuse} when N<Nmax ->
+ timer:sleep(10*N), % Sleep 10, 20, 30,... ms
+ try_listen(Port, Opts, N+1, Nmax);
+ Other ->
+ Other
+ end.
+
+
request_ownership(LSock, SockOwner) ->
SockOwner ! {request_control,LSock,self()},
receive