aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjuhlig <[email protected]>2020-04-20 17:03:17 +0200
committerjuhlig <[email protected]>2020-04-20 17:03:17 +0200
commit9765f305e1f55f758a683bd95665fd0ab84a52c3 (patch)
treea45cf397516b3e59f7a8065e7f76bba46a64e3d7
parent821937cea1a9afacd2dc2448440ad6f64d3a29f1 (diff)
downloadranch-9765f305e1f55f758a683bd95665fd0ab84a52c3.tar.gz
ranch-9765f305e1f55f758a683bd95665fd0ab84a52c3.tar.bz2
ranch-9765f305e1f55f758a683bd95665fd0ab84a52c3.zip
Delete local socket file when a listener closes
-rw-r--r--src/ranch.erl5
-rw-r--r--src/ranch_ssl.erl23
-rw-r--r--src/ranch_tcp.erl23
-rw-r--r--src/ranch_transport.erl1
-rw-r--r--test/acceptor_SUITE.erl21
5 files changed, 49 insertions, 24 deletions
diff --git a/src/ranch.erl b/src/ranch.erl
index a400798..7a03ef2 100644
--- a/src/ranch.erl
+++ b/src/ranch.erl
@@ -155,10 +155,13 @@ start_error(_, Error) -> Error.
-spec stop_listener(ref()) -> ok | {error, not_found}.
stop_listener(Ref) ->
+ [_, Transport, _, _, _] = ranch_server:get_listener_start_args(Ref),
+ TransOpts = get_transport_options(Ref),
case supervisor:terminate_child(ranch_sup, {ranch_listener_sup, Ref}) of
ok ->
_ = supervisor:delete_child(ranch_sup, {ranch_listener_sup, Ref}),
- ranch_server:cleanup_listener_opts(Ref);
+ ranch_server:cleanup_listener_opts(Ref),
+ Transport:cleanup(TransOpts);
{error, Reason} ->
{error, Reason}
end.
diff --git a/src/ranch_ssl.erl b/src/ranch_ssl.erl
index cc51012..2c35c97 100644
--- a/src/ranch_ssl.erl
+++ b/src/ranch_ssl.erl
@@ -43,6 +43,7 @@
-export([sockname/1]).
-export([shutdown/2]).
-export([close/1]).
+-export([cleanup/1]).
-type ssl_opt() :: {alpn_preferred_protocols, [binary()]}
| {beast_mitigation, one_n_minus_one | zero_n | disabled}
@@ -107,6 +108,7 @@ messages() -> {ssl, ssl_closed, ssl_error, ssl_passive}.
-spec listen(ranch:transport_opts(opts())) -> {ok, ssl:sslsocket()} | {error, atom()}.
listen(TransOpts) ->
+ ok = cleanup(TransOpts),
SocketOpts = maps:get(socket_opts, TransOpts, []),
case lists:keymember(cert, 1, SocketOpts)
orelse lists:keymember(certfile, 1, SocketOpts)
@@ -124,15 +126,6 @@ do_listen(SocketOpts0, Logger) ->
SocketOpts2 = ranch:set_option_default(SocketOpts1, nodelay, true),
SocketOpts3 = ranch:set_option_default(SocketOpts2, send_timeout, 30000),
SocketOpts = ranch:set_option_default(SocketOpts3, send_timeout_close, true),
- %% In case of a local socket, we remove the socket file first.
- %% It is possible to have multiple ip tuples in the socket options,
- %% and the last one will be used (undocumented).
- _ = case lists:keyfind(ip, 1, lists:reverse(SocketOpts0)) of
- {ip, {local, SockFile}} ->
- file:delete(SockFile);
- _ ->
- ok
- end,
%% We set the port to 0 because it is given in the Opts directly.
%% The port in the options takes precedence over the one in the
%% first argument.
@@ -287,3 +280,15 @@ shutdown(Socket, How) ->
-spec close(ssl:sslsocket()) -> ok.
close(Socket) ->
ssl:close(Socket).
+
+-spec cleanup(ranch:transport_opts(opts())) -> ok.
+cleanup(#{socket_opts:=SocketOpts}) ->
+ case lists:keyfind(ip, 1, lists:reverse(SocketOpts)) of
+ {ip, {local, SockFile}} ->
+ _ = file:delete(SockFile),
+ ok;
+ _ ->
+ ok
+ end;
+cleanup(_) ->
+ ok.
diff --git a/src/ranch_tcp.erl b/src/ranch_tcp.erl
index 4abd088..28d221c 100644
--- a/src/ranch_tcp.erl
+++ b/src/ranch_tcp.erl
@@ -43,6 +43,7 @@
-export([sockname/1]).
-export([shutdown/2]).
-export([close/1]).
+-export([cleanup/1]).
-type opt() :: {backlog, non_neg_integer()}
| {buffer, non_neg_integer()}
@@ -86,21 +87,13 @@ messages() -> {tcp, tcp_closed, tcp_error, tcp_passive}.
-spec listen(ranch:transport_opts(opts())) -> {ok, inet:socket()} | {error, atom()}.
listen(TransOpts) ->
+ ok = cleanup(TransOpts),
Logger = maps:get(logger, TransOpts, logger),
SocketOpts0 = maps:get(socket_opts, TransOpts, []),
SocketOpts1 = ranch:set_option_default(SocketOpts0, backlog, 1024),
SocketOpts2 = ranch:set_option_default(SocketOpts1, nodelay, true),
SocketOpts3 = ranch:set_option_default(SocketOpts2, send_timeout, 30000),
SocketOpts4 = ranch:set_option_default(SocketOpts3, send_timeout_close, true),
- %% In case of a local socket, we remove the socket file first.
- %% It is possible to have multiple ip tuples in the socket options,
- %% and the last one will be used (undocumented).
- _ = case lists:keyfind(ip, 1, lists:reverse(SocketOpts0)) of
- {ip, {local, SockFile}} ->
- file:delete(SockFile);
- _ ->
- ok
- end,
%% We set the port to 0 because it is given in the Opts directly.
%% The port in the options takes precedence over the one in the
%% first argument.
@@ -271,3 +264,15 @@ shutdown(Socket, How) ->
-spec close(inet:socket()) -> ok.
close(Socket) ->
gen_tcp:close(Socket).
+
+-spec cleanup(ranch:transport_opts(opts())) -> ok.
+cleanup(#{socket_opts:=SocketOpts}) ->
+ case lists:keyfind(ip, 1, lists:reverse(SocketOpts)) of
+ {ip, {local, SockFile}} ->
+ _ = file:delete(SockFile),
+ ok;
+ _ ->
+ ok
+ end;
+cleanup(_) ->
+ ok.
diff --git a/src/ranch_transport.erl b/src/ranch_transport.erl
index 5fd6242..23d9d5c 100644
--- a/src/ranch_transport.erl
+++ b/src/ranch_transport.erl
@@ -66,6 +66,7 @@
-callback shutdown(socket(), read | write | read_write)
-> ok | {error, atom()}.
-callback close(socket()) -> ok.
+-callback cleanup(ranch:transport_opts(any())) -> ok.
%% A fallback for transports that don't have a native sendfile implementation.
%% Note that the ordering of arguments is different from file:sendfile/5 and
diff --git a/test/acceptor_SUITE.erl b/test/acceptor_SUITE.erl
index 19b7057..290d041 100644
--- a/test/acceptor_SUITE.erl
+++ b/test/acceptor_SUITE.erl
@@ -77,7 +77,7 @@ groups() ->
misc_opts_logger,
misc_set_transport_options,
misc_wait_for_connections,
- misc_multiple_ips_in_listen_opts
+ misc_multiple_ip_local_socket_opts
]}, {supervisor, [
connection_type_supervisor,
connection_type_supervisor_separate_from_connection,
@@ -405,15 +405,15 @@ do_expect_waiter(WaiterPid) ->
end
end.
-misc_multiple_ips_in_listen_opts(_) ->
+misc_multiple_ip_local_socket_opts(_) ->
case do_os_supports_local_sockets() of
true ->
- do_misc_multiple_ips_in_listen_opts();
+ do_misc_multiple_ip_local_socket_opts();
false ->
{skip, "No local socket support."}
end.
-do_misc_multiple_ips_in_listen_opts() ->
+do_misc_multiple_ip_local_socket_opts() ->
doc("Ensure that a listener uses the expected ip option if multiple are given."),
Name = name(),
SockFile1 = do_tempname(),
@@ -421,7 +421,14 @@ do_misc_multiple_ips_in_listen_opts() ->
Opts = [{ip, {local, SockFile1}}, {ip, {local, SockFile2}}],
{ok, _} = ranch:start_listener(Name, ranch_tcp, #{socket_opts => Opts}, echo_protocol, []),
{local, SockFile2} = ranch:get_addr(Name),
- ok = ranch:stop_listener(Name).
+ %% Make sure the socket file from the ignored ip option
+ %% has not been created.
+ {error, enoent} = file:read_file_info(SockFile1),
+ ok = ranch:stop_listener(Name),
+ %% Make sure the socket file from the accepted ip option
+ %% is removed.
+ {error, enoent} = file:read_file_info(SockFile2),
+ ok.
%% ssl.
@@ -607,6 +614,8 @@ do_ssl_local_echo() ->
{error, closed} = ssl:recv(Socket, 0, 1000),
%% Make sure the listener stopped.
{'EXIT', _} = begin catch ranch:get_port(Name) end,
+ %% Make sure the socket file is removed.
+ {error, enoent} = file:read_file_info(SockFile),
ok
after
file:delete(SockFile)
@@ -900,6 +909,8 @@ do_tcp_local_echo() ->
{error, closed} = gen_tcp:recv(Socket, 0, 1000),
%% Make sure the listener stopped.
{'EXIT', _} = begin catch ranch:get_port(Name) end,
+ %% Make sure the socket file is removed.
+ {error, enoent} = file:read_file_info(SockFile),
ok
after
file:delete(SockFile)