Skip to content

Commit d58c1e6

Browse files
authored
Merge pull request #402 from systream/make_sure_socket_closed_on_tls_error
Make sure the connection closed on startup error
2 parents 07c9582 + 5e8d0fd commit d58c1e6

File tree

2 files changed

+31
-11
lines changed

2 files changed

+31
-11
lines changed

src/riakc_pb_socket.erl

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,13 @@
194194
ssl_opts = [], % Arbitrary SSL options, see the erlang SSL
195195
% documentation.
196196
reconnect_interval=?FIRST_RECONNECT_INTERVAL :: non_neg_integer(),
197-
silence_terminate_crash = false :: boolean()}).
197+
silence_terminate_crash = false :: boolean(),
198+
% Determines the time-out, in seconds,
199+
% for flushing unsent data in the close/1 socket call.
200+
% The first component is if linger is enabled,
201+
% the second component is the flushing time-out, in seconds.
202+
% https://erlang.org/doc/man/inet.html#setopts-2
203+
linger = {false, 0} :: {boolean(), non_neg_integer()}}).
198204

199205
-export_type([address/0, portnum/0]).
200206

@@ -2187,7 +2193,10 @@ parse_options([{keyfile, File}|Options], State) ->
21872193
parse_options([{ssl_opts, Opts}|Options], State) ->
21882194
parse_options(Options, State#state{ssl_opts=Opts});
21892195
parse_options([{silence_terminate_crash,Bool}|Options], State) ->
2190-
parse_options(Options, State#state{silence_terminate_crash=Bool}).
2196+
parse_options(Options, State#state{silence_terminate_crash=Bool});
2197+
parse_options([{linger, {Bool, Timeout}}|Options], State)
2198+
when Bool =:= true; Bool =:= false; Timeout>=0 ->
2199+
parse_options(Options, State#state{linger = {Bool, Timeout}}).
21912200

21922201
maybe_reply({reply, Reply, State}) ->
21932202
Request = State#state.active,
@@ -3086,6 +3095,7 @@ connect(State) when State#state.sock =:= undefined ->
30863095
#state{address = Address, port = Port, connects = Connects} = State,
30873096
case gen_tcp:connect(Address, Port,
30883097
[binary, {active, once}, {packet, 4},
3098+
{linger, State#state.linger},
30893099
{keepalive, State#state.keepalive}],
30903100
State#state.connect_timeout) of
30913101
{ok, Sock} ->
@@ -3138,6 +3148,7 @@ start_tls(State=#state{sock=Sock}) ->
31383148
%% man-in-the-middle proxy that presents insecure
31393149
%% communication to the client, but does secure
31403150
%% communication to the server.
3151+
ensure_connection_closed(State),
31413152
{error, no_security}
31423153
end
31433154
end.
@@ -3173,16 +3184,8 @@ disconnect(State) ->
31733184
end,
31743185

31753186
%% Make sure the connection is really closed
3176-
case State#state.sock of
3177-
undefined ->
3178-
ok;
3179-
Sock ->
3180-
Transport = State#state.transport,
3181-
Transport:close(Sock)
3182-
end,
3183-
3187+
NewState = ensure_connection_closed(State),
31843188
%% Decide whether to reconnect or exit
3185-
NewState = State#state{sock = undefined, active = undefined},
31863189
case State#state.auto_reconnect of
31873190
true ->
31883191
%% Schedule the reconnect message and return state
@@ -3197,6 +3200,12 @@ disconnect(State) ->
31973200
end
31983201
end.
31993202

3203+
ensure_connection_closed(#state{sock = undefined} = State) ->
3204+
State;
3205+
ensure_connection_closed(#state{sock = Sock, transport = Transport} = State) ->
3206+
Transport:close(Sock),
3207+
State#state{sock = undefined, active = undefined}.
3208+
32003209
%% Double the reconnect interval up to the maximum
32013210
increase_reconnect_interval(State) ->
32023211
case State#state.reconnect_interval of

test/riakc_pb_socket_tests.erl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,17 @@ auto_reconnect_server_closes_socket_test() ->
102102
?assertMatch({false, []}, riakc_pb_socket:is_connected(Pid)),
103103
riakc_pb_socket:stop(Pid).
104104

105+
linger_closes_socket_test() ->
106+
{ok, Listen} = gen_tcp:listen(0, [binary, {packet, 4}, {active, false}]),
107+
{ok, Port} = inet:port(Listen),
108+
{ok, Pid} = riakc_pb_socket:start_link("127.0.0.1", Port, [{linger, {true, 0}}]),
109+
{ok, Sock} = gen_tcp:accept(Listen),
110+
?assertMatch(true, riakc_pb_socket:is_connected(Pid)),
111+
riakc_pb_socket:stop(Pid),
112+
{error, closed} = gen_tcp:recv(Sock, 0),
113+
ok = gen_tcp:close(Sock),
114+
ok = gen_tcp:close(Listen).
115+
105116
dead_socket_pid_returns_to_caller_test() ->
106117
%% Set up a dummy socket to send requests on
107118
{ok, Listen} = gen_tcp:listen(0, [binary, {packet, 4}, {active, false}]),

0 commit comments

Comments
 (0)