diff options
author | James Fish <[email protected]> | 2013-04-01 23:15:45 +0100 |
---|---|---|
committer | James Fish <[email protected]> | 2013-04-02 17:51:07 +0100 |
commit | a700368b2cb021bb1cd007697db4a3bae0099f2d (patch) | |
tree | b745209e415ffcc597c2957d8dfe2acc22a6b0f6 /src | |
parent | 8203188155aa9243a4cdcec4962d9b190d2acb5b (diff) | |
download | ranch-a700368b2cb021bb1cd007697db4a3bae0099f2d.tar.gz ranch-a700368b2cb021bb1cd007697db4a3bae0099f2d.tar.bz2 ranch-a700368b2cb021bb1cd007697db4a3bae0099f2d.zip |
Fix ranch_server:set_connections_sup/2 race conditions
A ranch_conns_sup could be (re)started and call
ranch_server:set_connections_sup/2 before ranch_server has handled the
predecessor's exit. This would cause the ranch_server to crash because
ets:insert_new/2 would return false.
This change allows ranch_server to handle this case by crashing the
calling process instead of itself.
Diffstat (limited to 'src')
-rw-r--r-- | src/ranch_server.erl | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/src/ranch_server.erl b/src/ranch_server.erl index 7557d53..200e29c 100644 --- a/src/ranch_server.erl +++ b/src/ranch_server.erl @@ -68,7 +68,8 @@ cleanup_listener_opts(Ref) -> %% @doc Set a connection supervisor associated with specific listener. -spec set_connections_sup(any(), pid()) -> ok. set_connections_sup(Ref, Pid) -> - gen_server:call(?MODULE, {set_connections_sup, Ref, Pid}). + true = gen_server:call(?MODULE, {set_connections_sup, Ref, Pid}), + ok. %% @doc Return the connection supervisor used by specific listener. -spec get_connections_sup(any()) -> pid(). @@ -125,10 +126,14 @@ handle_call({set_new_listener_opts, Ref, MaxConns, Opts}, _, State) -> {reply, ok, State}; handle_call({set_connections_sup, Ref, Pid}, _, State=#state{monitors=Monitors}) -> - true = ets:insert_new(?TAB, {{conns_sup, Ref}, Pid}), - MonitorRef = erlang:monitor(process, Pid), - {reply, ok, State#state{ - monitors=[{{MonitorRef, Pid}, Ref}|Monitors]}}; + case ets:insert_new(?TAB, {{conns_sup, Ref}, Pid}) of + true -> + MonitorRef = erlang:monitor(process, Pid), + {reply, true, + State#state{monitors=[{{MonitorRef, Pid}, Ref}|Monitors]}}; + false -> + {reply, false, State} + end; handle_call({set_port, Ref, Port}, _, State) -> true = ets:insert(?TAB, {{port, Ref}, Port}), {reply, ok, State}; |