Просмотр исходного кода

Supervised and connection process can now be different

Loïc Hoguin 9 лет назад
Родитель
Сommit
52797b0610
2 измененных файлов с 49 добавлено и 20 удалено
  1. 24 0
      guide/listeners.md
  2. 25 20
      src/ranch_conns_sup.erl

+ 24 - 0
guide/listeners.md

@@ -192,6 +192,30 @@ ranch:set_max_connections(tcp_echo, MaxConns).
 
 The change will occur immediately.
 
+Using a supervisor for connection processes
+-------------------------------------------
+
+Ranch allows you to define the type of process that will be used
+for the connection processes. By default it expects a `worker`.
+When the `connection_type` configuration value is set to `supervisor`,
+Ranch will consider that the connection process it manages is a
+supervisor and will reflect that in its supervision tree.
+
+Connection processes of type `supervisor` can either handle the
+socket directly or through one of their children. In the latter
+case the start function for the connection process must return
+two pids: the pid of the supervisor you created (that will be
+supervised) and the pid of the protocol handling process (that
+will receive the socket).
+
+Instead of returning `{ok, ConnPid}`, simply return
+`{ok, SupPid, ConnPid}`.
+
+It is very important that the connection process be created
+under the supervisor process so that everything works as intended.
+If not, you will most likely experience issues when the supervised
+process is stopped.
+
 Upgrading
 ---------
 

+ 25 - 20
src/ranch_conns_sup.erl

@@ -108,30 +108,14 @@ init(Parent, Ref, ConnType, Shutdown, Transport, AckTimeout, Protocol) ->
 
 loop(State=#state{parent=Parent, ref=Ref, conn_type=ConnType,
 		transport=Transport, protocol=Protocol, opts=Opts,
-		ack_timeout=AckTimeout, max_conns=MaxConns},
-		CurConns, NbChildren, Sleepers) ->
+		max_conns=MaxConns}, CurConns, NbChildren, Sleepers) ->
 	receive
 		{?MODULE, start_protocol, To, Socket} ->
 			case Protocol:start_link(Ref, Socket, Transport, Opts) of
 				{ok, Pid} ->
-					case Transport:controlling_process(Socket, Pid) of
-						ok ->
-							Pid ! {shoot, Ref, Transport, Socket, AckTimeout},
-							put(Pid, true),
-							CurConns2 = CurConns + 1,
-							if CurConns2 < MaxConns ->
-									To ! self(),
-									loop(State, CurConns2, NbChildren + 1,
-										Sleepers);
-								true ->
-									loop(State, CurConns2, NbChildren + 1,
-										[To|Sleepers])
-							end;
-						{error, _} ->
-							Transport:close(Socket),
-							exit(Pid, kill),
-							loop(State, CurConns, NbChildren, Sleepers)
-					end;
+					shoot(State, CurConns, NbChildren, Sleepers, To, Socket, Pid, Pid);
+				{ok, SupPid, ProtocolPid} when ConnType =:= supervisor ->
+					shoot(State, CurConns, NbChildren, Sleepers, To, Socket, SupPid, ProtocolPid);
 				Ret ->
 					To ! self(),
 					error_logger:error_msg(
@@ -200,6 +184,27 @@ loop(State=#state{parent=Parent, ref=Ref, conn_type=ConnType,
 				[Ref, Msg])
 	end.
 
+shoot(State=#state{ref=Ref, transport=Transport, ack_timeout=AckTimeout, max_conns=MaxConns},
+		CurConns, NbChildren, Sleepers, To, Socket, SupPid, ProtocolPid) ->
+	case Transport:controlling_process(Socket, ProtocolPid) of
+		ok ->
+			ProtocolPid ! {shoot, Ref, Transport, Socket, AckTimeout},
+			put(SupPid, true),
+			CurConns2 = CurConns + 1,
+			if CurConns2 < MaxConns ->
+					To ! self(),
+					loop(State, CurConns2, NbChildren + 1, Sleepers);
+				true ->
+					loop(State, CurConns2, NbChildren + 1, [To|Sleepers])
+			end;
+		{error, _} ->
+			Transport:close(Socket),
+			%% Only kill the supervised pid, because the connection's pid,
+			%% when different, is supposed to be sitting under it and linked.
+			exit(SupPid, kill),
+			loop(State, CurConns, NbChildren, Sleepers)
+	end.
+
 -spec terminate(#state{}, any(), non_neg_integer()) -> no_return().
 %% Kill all children and then exit. We unlink first to avoid
 %% getting a message for each child getting killed.