From b9c8d86502a76cf3a72af30fc6aa0fc88ca7afff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Tue, 13 Mar 2018 10:40:14 +0100 Subject: Handle supervisor calls properly everywhere --- src/cowboy_children.erl | 21 +++++++++++++++++++-- src/cowboy_http.erl | 10 ++-------- src/cowboy_http2.erl | 10 ++-------- src/cowboy_websocket.erl | 4 ++++ 4 files changed, 27 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/cowboy_children.erl b/src/cowboy_children.erl index 1927a5a..05d39fb 100644 --- a/src/cowboy_children.erl +++ b/src/cowboy_children.erl @@ -20,8 +20,7 @@ -export([shutdown/2]). -export([shutdown_timeout/3]). -export([terminate/1]). --export([which_children/2]). --export([count_children/1]). +-export([handle_supervisor_call/4]). -record(child, { pid :: pid(), @@ -160,6 +159,24 @@ longest_shutdown_time([#child{shutdown=ChildTime}|Tail], Time) when ChildTime > longest_shutdown_time([_|Tail], Time) -> longest_shutdown_time(Tail, Time). +-spec handle_supervisor_call(any(), {pid(), any()}, children(), module()) -> ok. +handle_supervisor_call(which_children, {From, Tag}, Children, Module) -> + From ! {Tag, which_children(Children, Module)}, + ok; +handle_supervisor_call(count_children, {From, Tag}, Children, _) -> + From ! {Tag, count_children(Children)}, + ok; +%% We disable start_child since only incoming requests +%% end up creating a new process. +handle_supervisor_call({start_child, _}, {From, Tag}, _, _) -> + From ! {Tag, {error, start_child_disabled}}, + ok; +%% All other calls refer to children. We act in a similar way +%% to a simple_one_for_one so we never find those. +handle_supervisor_call(_, {From, Tag}, _, _) -> + From ! {Tag, {error, not_found}}, + ok. + -spec which_children(children(), module()) -> [{module(), pid(), worker, [module()]}]. which_children(Children, Module) -> [{Module, Pid, worker, [Module]} || #child{pid=Pid} <- Children]. diff --git a/src/cowboy_http.erl b/src/cowboy_http.erl index fa09480..62e5176 100644 --- a/src/cowboy_http.erl +++ b/src/cowboy_http.erl @@ -202,14 +202,8 @@ loop(State=#state{parent=Parent, socket=Socket, transport=Transport, opts=Opts, Msg = {'EXIT', Pid, _} -> loop(down(State, Pid, Msg), Buffer); %% Calls from supervisor module. - {'$gen_call', {From, Tag}, which_children} -> - From ! {Tag, cowboy_children:which_children(Children, ?MODULE)}, - loop(State, Buffer); - {'$gen_call', {From, Tag}, count_children} -> - From ! {Tag, cowboy_children:count_children(Children)}, - loop(State, Buffer); - {'$gen_call', {From, Tag}, _} -> - From ! {Tag, {error, ?MODULE}}, + {'$gen_call', From, Call} -> + cowboy_children:handle_supervisor_call(Call, From, Children, ?MODULE), loop(State, Buffer); %% Unknown messages. Msg -> diff --git a/src/cowboy_http2.erl b/src/cowboy_http2.erl index 6399346..7dbfb24 100644 --- a/src/cowboy_http2.erl +++ b/src/cowboy_http2.erl @@ -247,14 +247,8 @@ loop(State=#state{parent=Parent, socket=Socket, transport=Transport, Msg = {'EXIT', Pid, _} -> loop(down(State, Pid, Msg), Buffer); %% Calls from supervisor module. - {'$gen_call', {From, Tag}, which_children} -> - From ! {Tag, cowboy_children:which_children(Children, ?MODULE)}, - loop(State, Buffer); - {'$gen_call', {From, Tag}, count_children} -> - From ! {Tag, cowboy_children:count_children(Children)}, - loop(State, Buffer); - {'$gen_call', {From, Tag}, _} -> - From ! {Tag, {error, ?MODULE}}, + {'$gen_call', From, Call} -> + cowboy_children:handle_supervisor_call(Call, From, Children, ?MODULE), loop(State, Buffer); Msg -> error_logger:error_msg("Received stray message ~p.", [Msg]), diff --git a/src/cowboy_websocket.erl b/src/cowboy_websocket.erl index ebb0fcd..6b59689 100644 --- a/src/cowboy_websocket.erl +++ b/src/cowboy_websocket.erl @@ -250,6 +250,10 @@ handler_loop(State=#state{socket=Socket, messages={OK, Closed, Error}, websocket_close(State, HandlerState, timeout); {timeout, OlderTRef, ?MODULE} when is_reference(OlderTRef) -> handler_loop(State, HandlerState, SoFar); + %% Calls from supervisor module. + {'$gen_call', From, Call} -> + cowboy_children:handle_supervisor_call(Call, From, [], ?MODULE), + handler_loop(State, HandlerState, SoFar); Message -> handler_call(State, HandlerState, SoFar, websocket_info, Message, fun handler_before_loop/3) -- cgit v1.2.3