From 963f53942f1106771e91a018ac9ad46e3bc6a777 Mon Sep 17 00:00:00 2001 From: "j.uhlig" Date: Fri, 4 May 2018 16:23:27 +0200 Subject: Ensure listener restart with changed TransOpts --- src/ranch_conns_sup.erl | 24 +++++++++++++----------- src/ranch_listener_sup.erl | 9 +++------ src/ranch_server.erl | 8 ++++---- test/acceptor_SUITE.erl | 38 ++++++++++++++++++++++++++++++++++++++ test/ranch_ct_hook.erl | 5 +++++ 5 files changed, 63 insertions(+), 21 deletions(-) diff --git a/src/ranch_conns_sup.erl b/src/ranch_conns_sup.erl index 6a2336f..812a6c3 100644 --- a/src/ranch_conns_sup.erl +++ b/src/ranch_conns_sup.erl @@ -18,12 +18,12 @@ -module(ranch_conns_sup). %% API. --export([start_link/6]). +-export([start_link/3]). -export([start_protocol/2]). -export([active_connections/1]). %% Supervisor internals. --export([init/7]). +-export([init/4]). -export([system_continue/3]). -export([system_terminate/4]). -export([system_code_change/4]). @@ -45,11 +45,10 @@ %% API. --spec start_link(ranch:ref(), conn_type(), shutdown(), module(), - timeout(), module()) -> {ok, pid()}. -start_link(Ref, ConnType, Shutdown, Transport, AckTimeout, Protocol) -> +-spec start_link(ranch:ref(), module(), module()) -> {ok, pid()}. +start_link(Ref, Transport, Protocol) -> proc_lib:start_link(?MODULE, init, - [self(), Ref, ConnType, Shutdown, Transport, AckTimeout, Protocol]). + [self(), Ref, Transport, Protocol]). %% We can safely assume we are on the same node as the supervisor. %% @@ -94,17 +93,20 @@ active_connections(SupPid) -> %% Supervisor internals. --spec init(pid(), ranch:ref(), conn_type(), shutdown(), - module(), timeout(), module()) -> no_return(). -init(Parent, Ref, ConnType, Shutdown, Transport, AckTimeout, Protocol) -> +-spec init(pid(), ranch:ref(), module(), module()) -> no_return(). +init(Parent, Ref, Transport, Protocol) -> process_flag(trap_exit, true), ok = ranch_server:set_connections_sup(Ref, self()), MaxConns = ranch_server:get_max_connections(Ref), - Opts = ranch_server:get_protocol_options(Ref), + TransOpts = ranch_server:get_transport_options(Ref), + ConnType = proplists:get_value(connection_type, TransOpts, worker), + Shutdown = proplists:get_value(shutdown, TransOpts, 5000), + AckTimeout = proplists:get_value(ack_timeout, TransOpts, 5000), + ProtoOpts = ranch_server:get_protocol_options(Ref), ok = proc_lib:init_ack(Parent, {ok, self()}), loop(#state{parent=Parent, ref=Ref, conn_type=ConnType, shutdown=Shutdown, transport=Transport, protocol=Protocol, - opts=Opts, ack_timeout=AckTimeout, max_conns=MaxConns}, 0, 0, []). + opts=ProtoOpts, ack_timeout=AckTimeout, max_conns=MaxConns}, 0, 0, []). loop(State=#state{parent=Parent, ref=Ref, conn_type=ConnType, transport=Transport, protocol=Protocol, opts=Opts, diff --git a/src/ranch_listener_sup.erl b/src/ranch_listener_sup.erl index 502df44..bd4ccc5 100644 --- a/src/ranch_listener_sup.erl +++ b/src/ranch_listener_sup.erl @@ -25,17 +25,14 @@ start_link(Ref, NumAcceptors, Transport, TransOpts, Protocol, ProtoOpts) -> ranch_server:set_new_listener_opts(Ref, MaxConns, TransOpts, ProtoOpts, [Ref, NumAcceptors, Transport, TransOpts, Protocol, ProtoOpts]), supervisor:start_link(?MODULE, { - Ref, NumAcceptors, Transport, TransOpts, Protocol + Ref, NumAcceptors, Transport, Protocol }). -init({Ref, NumAcceptors, Transport, TransOpts, Protocol}) -> +init({Ref, NumAcceptors, Transport, Protocol}) -> ok = ranch_server:set_listener_sup(Ref, self()), - AckTimeout = proplists:get_value(ack_timeout, TransOpts, 5000), - ConnType = proplists:get_value(connection_type, TransOpts, worker), - Shutdown = proplists:get_value(shutdown, TransOpts, 5000), ChildSpecs = [ {ranch_conns_sup, {ranch_conns_sup, start_link, - [Ref, ConnType, Shutdown, Transport, AckTimeout, Protocol]}, + [Ref, Transport, Protocol]}, permanent, infinity, supervisor, [ranch_conns_sup]}, {ranch_acceptors_sup, {ranch_acceptors_sup, start_link, [Ref, NumAcceptors, Transport]}, diff --git a/src/ranch_server.erl b/src/ranch_server.erl index 80f82d6..015c9f9 100644 --- a/src/ranch_server.erl +++ b/src/ranch_server.erl @@ -156,10 +156,10 @@ init([]) -> {ok, #state{monitors=ConnMonitors++ListenerMonitors}}. handle_call({set_new_listener_opts, Ref, MaxConns, TransOpts, ProtoOpts, StartArgs}, _, State) -> - ets:insert(?TAB, {{max_conns, Ref}, MaxConns}), - ets:insert(?TAB, {{trans_opts, Ref}, TransOpts}), - ets:insert(?TAB, {{proto_opts, Ref}, ProtoOpts}), - ets:insert(?TAB, {{listener_start_args, Ref}, StartArgs}), + ets:insert_new(?TAB, {{max_conns, Ref}, MaxConns}), + ets:insert_new(?TAB, {{trans_opts, Ref}, TransOpts}), + ets:insert_new(?TAB, {{proto_opts, Ref}, ProtoOpts}), + ets:insert_new(?TAB, {{listener_start_args, Ref}, StartArgs}), {reply, ok, State}; handle_call({set_connections_sup, Ref, Pid}, _, State=#state{monitors=Monitors}) -> diff --git a/test/acceptor_SUITE.erl b/test/acceptor_SUITE.erl index e441b51..4918642 100644 --- a/test/acceptor_SUITE.erl +++ b/test/acceptor_SUITE.erl @@ -62,6 +62,7 @@ groups() -> ]}, {supervisor, [ connection_type_supervisor, connection_type_supervisor_separate_from_connection, + supervisor_changed_options_restart, supervisor_clean_child_restart, supervisor_clean_conns_sup_restart, supervisor_clean_restart, @@ -799,6 +800,36 @@ connection_type_supervisor_separate_from_connection(_) -> {'EXIT', _} = begin catch ranch:get_port(Name) end, ok. +supervisor_changed_options_restart(_) -> + doc("Ensure that a listener is restarted with changed transport options."), + Name = name(), + %% Start a listener using send_timeout as option change marker. + {ok, ListenerSupPid1} = ranch:start_listener(Name, + ranch_tcp, [{send_timeout, 300000}], + echo_protocol, []), + %% Ensure send_timeout is really set to initial value. + {ok, [{send_timeout, 300000}]} + = inet:getopts(do_get_listener_socket(ListenerSupPid1), [send_timeout]), + %% Change send_timeout option. + ok = ranch:suspend_listener(Name), + ok = ranch:set_transport_options(Name, [{send_timeout, 300001}]), + ok = ranch:resume_listener(Name), + %% Ensure send_timeout is really set to the changed value. + {ok, [{send_timeout, 300001}]} + = inet:getopts(do_get_listener_socket(ListenerSupPid1), [send_timeout]), + %% Crash the listener_sup process, allow a short time for restart to succeed. + exit(ListenerSupPid1, kill), + timer:sleep(1000), + %% Obtain pid of restarted listener_sup process. + [ListenerSupPid2] = [Pid || {{ranch_listener_sup, Ref}, Pid, supervisor, _} + <- supervisor:which_children(ranch_sup), Ref =:= Name], + %% Ensure send_timeout is still set to the changed value. + {ok, [{send_timeout, 300001}]} + = inet:getopts(do_get_listener_socket(ListenerSupPid2), [send_timeout]), + ok = ranch:stop_listener(Name), + {'EXIT', _} = begin catch ranch:get_port(Name) end, + ok. + supervisor_clean_child_restart(Config) -> case code:is_module_native(?MODULE) of true -> doc("This test uses tracing and is not compatible with native code."); @@ -1034,3 +1065,10 @@ clean_traces() -> after 0 -> ok end. + +do_get_listener_socket(ListenerSupPid) -> + [AcceptorsSupPid] = [Pid || {ranch_acceptors_sup, Pid, supervisor, _} + <- supervisor:which_children(ListenerSupPid)], + {links, Links} = erlang:process_info(AcceptorsSupPid, links), + [LSocket] = [P || P <- Links, is_port(P)], + LSocket. diff --git a/test/ranch_ct_hook.erl b/test/ranch_ct_hook.erl index 183cdf5..07f89df 100644 --- a/test/ranch_ct_hook.erl +++ b/test/ranch_ct_hook.erl @@ -17,6 +17,11 @@ -export([init/2]). init(_, _) -> + %% Allow a more relaxed restart intensity because + %% some tests will cause quick restarts of several + %% ranch_sup children. + application:set_env(ranch, ranch_sup_intensity, 10), + application:set_env(ranch, ranch_sup_period, 1), ct_helper:start([ranch]), ct_helper:make_certs_in_ets(), error_logger:add_report_handler(ct_helper_error_h), -- cgit v1.2.3