summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Klishin <mklishin@pivotal.io>2018-10-11 01:47:41 +0300
committerMichael Klishin <mklishin@pivotal.io>2018-10-11 01:47:41 +0300
commit77bf5d6f2a1c2a9ce5483c384af22245f7b190a5 (patch)
treee4d7cb66524a442505ea2023a498ef4d92855cc8 /src
parent3ae27d2e5a0128c65d1e1312a23ef72103298e9a (diff)
downloadrabbitmq-server-git-77bf5d6f2a1c2a9ce5483c384af22245f7b190a5.tar.gz
Refactor listener startup error handling
Functions that start listeners (Ranch supervisors) no longer throw on errors. They simply return the first error encountered and let the boot step handle it. Since there is no way for boot steps to indicate errors, this is the best we can do in this area without a much deeper refactoring of the boot sequence. In addition they also log the error. Note that modern Ranch versions log more reasonable messages when Ranch supervisors exit due to a listen/bind socket operation error, e.g. when the address/port pair is already in use. Closes #1711 (for now), covers #1729 for the server as a drive-by change. [#160791138] [#161136615]
Diffstat (limited to 'src')
-rw-r--r--src/rabbit_networking.erl63
1 files changed, 46 insertions, 17 deletions
diff --git a/src/rabbit_networking.erl b/src/rabbit_networking.erl
index 399b1143d3..f6f8d226d0 100644
--- a/src/rabbit_networking.erl
+++ b/src/rabbit_networking.erl
@@ -68,9 +68,10 @@
-type protocol() :: atom().
-type label() :: string().
--spec start_tcp_listener(listener_config(), integer()) -> 'ok'.
--spec start_ssl_listener
- (listener_config(), rabbit_types:infos(), integer()) -> 'ok'.
+-spec start_tcp_listener(
+ listener_config(), integer()) -> 'ok' | {'error', term()}.
+-spec start_ssl_listener(
+ listener_config(), rabbit_types:infos(), integer()) -> 'ok' | {'error', term()}.
-spec stop_tcp_listener(listener_config()) -> 'ok'.
-spec active_listeners() -> [rabbit_types:listener()].
-spec node_listeners(node()) -> [rabbit_types:listener()].
@@ -118,17 +119,35 @@
boot() ->
ok = record_distribution_listener(),
_ = application:start(ranch),
- ok = boot_tcp(application:get_env(rabbit, num_tcp_acceptors, 10)),
- ok = boot_ssl(application:get_env(rabbit, num_ssl_acceptors, 1)),
+ %% Failures will throw exceptions
+ _ = boot_listeners(fun boot_tcp/1, application:get_env(rabbit, num_tcp_acceptors, 10), "TCP"),
+ _ = boot_listeners(fun boot_tls/1, application:get_env(rabbit, num_ssl_acceptors, 10), "TLS"),
_ = maybe_start_proxy_protocol(),
ok.
+boot_listeners(Fun, NumAcceptors, Type) ->
+ case Fun(NumAcceptors) of
+ ok ->
+ ok;
+ {error, {could_not_start_listener, Address, Port, Details}} = Error ->
+ rabbit_log:error("Failed to start ~s listener [~s]:~p, error: ~p",
+ [Type, Address, Port, Details]),
+ throw(Error)
+ end.
+
boot_tcp(NumAcceptors) ->
{ok, TcpListeners} = application:get_env(tcp_listeners),
- [ok = start_tcp_listener(Listener, NumAcceptors) || Listener <- TcpListeners],
- ok.
+ case lists:foldl(fun(Listener, ok) ->
+ start_tcp_listener(Listener, NumAcceptors);
+ (_Listener, Error) ->
+ Error
+ end,
+ ok, TcpListeners) of
+ ok -> ok;
+ {error, _} = Error -> Error
+ end.
-boot_ssl(NumAcceptors) ->
+boot_tls(NumAcceptors) ->
case application:get_env(ssl_listeners) of
{ok, []} ->
ok;
@@ -212,15 +231,20 @@ tcp_listener_spec(NamePrefix, {IPAddress, Port, Family}, SocketOpts,
transient, infinity, supervisor, [tcp_listener_sup]}.
start_tcp_listener(Listener, NumAcceptors) ->
- start_listener(Listener, NumAcceptors, amqp, "TCP Listener", tcp_opts()).
+ start_listener(Listener, NumAcceptors, amqp, "TCP listener", tcp_opts()).
start_ssl_listener(Listener, SslOpts, NumAcceptors) ->
- start_listener(Listener, NumAcceptors, 'amqp/ssl', "SSL Listener", tcp_opts() ++ SslOpts).
+ start_listener(Listener, NumAcceptors, 'amqp/ssl', "TLS (SSL) listener", tcp_opts() ++ SslOpts).
+
+-spec start_listener(
+ listener_config(), integer(), protocol(), label(), list()) -> 'ok' | {'error', term()}.
start_listener(Listener, NumAcceptors, Protocol, Label, Opts) ->
- [start_listener0(Address, NumAcceptors, Protocol, Label, Opts) ||
- Address <- tcp_listener_addresses(Listener)],
- ok.
+ lists:foldl(fun (Address, ok) ->
+ start_listener0(Address, NumAcceptors, Protocol, Label, Opts);
+ (_Address, {error, _} = Error) ->
+ Error
+ end, ok, tcp_listener_addresses(Listener)).
start_listener0(Address, NumAcceptors, Protocol, Label, Opts) ->
Transport = transport(Protocol),
@@ -228,10 +252,15 @@ start_listener0(Address, NumAcceptors, Protocol, Label, Opts) ->
Transport, rabbit_connection_sup, [], Protocol,
NumAcceptors, Label),
case supervisor:start_child(rabbit_sup, Spec) of
- {ok, _} -> ok;
- {error, {shutdown, _}} -> {IPAddress, Port, _Family} = Address,
- exit({could_not_start_tcp_listener,
- {rabbit_misc:ntoa(IPAddress), Port}})
+ {ok, _} -> ok;
+ {error, {{shutdown, {failed_to_start_child, _,
+ {shutdown, {failed_to_start_child, _,
+ {listen_error, _, PosixError}}}}}, _}} ->
+ {IPAddress, Port, _Family} = Address,
+ {error, {could_not_start_listener, rabbit_misc:ntoa(IPAddress), Port, PosixError}};
+ {error, Other} ->
+ {IPAddress, Port, _Family} = Address,
+ {error, {could_not_start_listener, rabbit_misc:ntoa(IPAddress), Port, Other}}
end.
transport(Protocol) ->