diff options
-rw-r--r-- | src/ranch_acceptor.erl | 18 | ||||
-rw-r--r-- | src/ranch_ssl.erl | 6 | ||||
-rw-r--r-- | test/acceptor_SUITE.erl | 17 |
3 files changed, 34 insertions, 7 deletions
diff --git a/src/ranch_acceptor.erl b/src/ranch_acceptor.erl index e03cde9..d208a7f 100644 --- a/src/ranch_acceptor.erl +++ b/src/ranch_acceptor.erl @@ -46,6 +46,11 @@ init(LSocket, Transport, Protocol, MaxConns, Opts, ListenerPid, ConnsSup) -> non_neg_integer(), any(), pid(), pid()) -> no_return(). loop(LSocket, Transport, Protocol, MaxConns, Opts, ListenerPid, ConnsSup) -> receive + %% We couldn't accept the socket but it's safe to continue. + {accept, continue} -> + ?MODULE:init(LSocket, Transport, Protocol, + MaxConns, Opts, ListenerPid, ConnsSup); + %% Found my sockets! {accept, CSocket} -> {ok, ConnPid} = supervisor:start_child(ConnsSup, [ListenerPid, CSocket, Transport, Protocol, Opts]), @@ -55,6 +60,7 @@ loop(LSocket, Transport, Protocol, MaxConns, Opts, ListenerPid, ConnsSup) -> maybe_wait(ListenerPid, MaxConns, NbConns), ?MODULE:init(LSocket, Transport, Protocol, MaxConns, Opts, ListenerPid, ConnsSup); + %% Upgrade the protocol options. {set_opts, Opts2} -> ?MODULE:loop(LSocket, Transport, Protocol, MaxConns, Opts2, ListenerPid, ConnsSup) @@ -72,9 +78,13 @@ maybe_wait(ListenerPid, MaxConns, _) -> async_accept(LSocket, Transport) -> AcceptorPid = self(), _ = spawn_link(fun() -> - %% @todo {error, closed} must be handled and other errors ignored. - {ok, CSocket} = Transport:accept(LSocket, infinity), - Transport:controlling_process(CSocket, AcceptorPid), - AcceptorPid ! {accept, CSocket} + case Transport:accept(LSocket, infinity) of + {ok, CSocket} -> + Transport:controlling_process(CSocket, AcceptorPid), + AcceptorPid ! {accept, CSocket}; + %% We want to crash if the listening socket got closed. + {error, Reason} when Reason =/= closed -> + AcceptorPid ! {accept, continue} + end end), ok. diff --git a/src/ranch_ssl.erl b/src/ranch_ssl.erl index 51ea128..d85c05f 100644 --- a/src/ranch_ssl.erl +++ b/src/ranch_ssl.erl @@ -111,7 +111,7 @@ listen(Opts) -> %% @see ssl:transport_accept/2 %% @see ssl:ssl_accept/2 -spec accept(ssl:sslsocket(), timeout()) - -> {ok, ssl:sslsocket()} | {error, closed | timeout | atom()}. + -> {ok, ssl:sslsocket()} | {error, closed | timeout | atom() | tuple()}. accept(LSocket, Timeout) -> case ssl:transport_accept(LSocket, Timeout) of {ok, CSocket} -> @@ -179,11 +179,11 @@ require([App|Tail]) -> require(Tail). -spec ssl_accept(ssl:sslsocket(), timeout()) - -> {ok, ssl:sslsocket()} | {error, closed | timeout | atom()}. + -> {ok, ssl:sslsocket()} | {error, {ssl_accept, atom()}}. ssl_accept(Socket, Timeout) -> case ssl:ssl_accept(Socket, Timeout) of ok -> {ok, Socket}; {error, Reason} -> - {error, Reason} + {error, {ssl_accept, Reason}} end. diff --git a/test/acceptor_SUITE.erl b/test/acceptor_SUITE.erl index 389f375..1c0931b 100644 --- a/test/acceptor_SUITE.erl +++ b/test/acceptor_SUITE.erl @@ -25,6 +25,7 @@ -export([end_per_group/2]). %% ssl. +-export([ssl_accept_error/1]). -export([ssl_echo/1]). %% tcp. @@ -45,6 +46,7 @@ groups() -> tcp_max_connections_and_beyond, tcp_upgrade ]}, {ssl, [ + ssl_accept_error, ssl_echo ]}]. @@ -74,6 +76,21 @@ end_per_group(_, _) -> %% ssl. +ssl_accept_error(Config) -> + {ok, _} = ranch:start_listener(ssl_accept_error, 1, + ranch_ssl, [{port, 0}, + {certfile, ?config(data_dir, Config) ++ "cert.pem"}], + echo_protocol, []), + Port = ranch:get_port(ssl_accept_error), + [AcceptorPid] = ets:lookup_element(ranch_server, + {acceptors, ssl_accept_error}, 2), + true = is_process_alive(AcceptorPid), + {ok, Socket} = gen_tcp:connect("localhost", Port, + [binary, {active, false}, {packet, raw}]), + ok = gen_tcp:close(Socket), + receive after 500 -> ok end, + true = is_process_alive(AcceptorPid). + ssl_echo(Config) -> {ok, _} = ranch:start_listener(ssl_echo, 1, ranch_ssl, [{port, 0}, |