Skip to content

Commit c36a97e

Browse files
spring2maztigercl
authored andcommitted
Fix acceptor: do not crash on closed socket when setting opts
If the socket (port) is closed (by client) before sending any data, acceptor may crash when setting active option. In this commit, the error posix code is captured and logged, then acceptor can stop.
1 parent fe2dd1d commit c36a97e

File tree

3 files changed

+14
-9
lines changed

3 files changed

+14
-9
lines changed

src/driver/gen_rpc_driver_ssl.erl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,9 @@ send(Socket, Data) when is_tuple(Socket), is_binary(Data) ->
8686
ok
8787
end.
8888

89-
-spec activate_socket(ssl:sslsocket()) -> ok.
89+
-spec activate_socket(ssl:sslsocket()) -> ok | {error, inet:posix()}.
9090
activate_socket(Socket) when is_tuple(Socket) ->
91-
ok = ssl:setopts(Socket, [{active,once}]),
92-
ok.
91+
ssl:setopts(Socket, [{active, once}]).
9392

9493
%% Authenticate to a server
9594
-spec authenticate_server(ssl:sslsocket()) -> ok | {error, {badtcp | badrpc, term()}}.

src/driver/gen_rpc_driver_tcp.erl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,9 @@ listen(Port) when is_integer(Port) ->
6262
accept(Socket) when is_port(Socket) ->
6363
gen_tcp:accept(Socket, infinity).
6464

65-
-spec activate_socket(port()) -> ok.
65+
-spec activate_socket(port()) -> ok | {error, inet:posix()}.
6666
activate_socket(Socket) when is_port(Socket) ->
67-
ok = inet:setopts(Socket, [{active,true}]),
68-
ok.
67+
inet:setopts(Socket, [{active,true}]).
6968

7069
-spec send(port(), binary()) -> ok | {error, term()}.
7170
send(Socket, Data) when is_port(Socket), is_binary(Data) ->

src/gen_rpc_acceptor.erl

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,21 @@ callback_mode() ->
8383

8484
waiting_for_socket({call,From}, {socket_ready,Socket}, #state{driver=Driver, driver_mod=DriverMod, peer=Peer} = State) ->
8585
ok = DriverMod:set_acceptor_opts(Socket),
86-
ok = DriverMod:activate_socket(Socket),
86+
ActivateResult = DriverMod:activate_socket(Socket),
8787
% Now we own the socket
8888
?log(debug, "event=acquiring_socket_ownership driver=~s socket=\"~s\" peer=\"~p\" inet_opts: ~0p",
8989
[Driver, gen_rpc_helper:socket_to_string(Socket),
9090
gen_rpc_helper:peer_to_string(Peer),
9191
prim_inet:getopts(Socket, [gen_rpc_helper:user_tcp_opt_key(Opt)|| Opt <- ?USER_TCP_OPTS])]),
9292
ok = gen_statem:reply(From, ok),
93-
{next_state, waiting_for_auth, State#state{socket=Socket}, gen_rpc_helper:get_authentication_timeout()}.
93+
case ActivateResult of
94+
ok ->
95+
{next_state, waiting_for_auth, State#state{socket=Socket}, gen_rpc_helper:get_authentication_timeout()};
96+
{error, _Posix} ->
97+
?log(notice, "message=channel_closed before receiving any data driver=~p socket=\"~s\" peer=\"~s\"",
98+
[Driver, gen_rpc_helper:socket_to_string(Socket), gen_rpc_helper:peer_to_string(Peer)]),
99+
{stop, normal, State}
100+
end.
94101

95102
waiting_for_auth(info, {Driver,Socket,Data}, #state{socket=Socket, driver=Driver, driver_mod=DriverMod, peer=Peer} = State) ->
96103
case DriverMod:authenticate_client(Socket, Peer, Data) of
@@ -309,4 +316,4 @@ handle_cast(UnknownReq, #state{socket=Socket, driver=Driver, peer=Peer}) ->
309316
?log(debug, "event=invalid_cast_req driver=~s socket=\"~s\" peer=\"~s\" req=\"~p\"",
310317
[Driver, gen_rpc_helper:socket_to_string(Socket),
311318
gen_rpc_helper:peer_to_string(Peer), UnknownReq]),
312-
error(invalid_cast_req).
319+
error(invalid_cast_req).

0 commit comments

Comments
 (0)