diff --git a/src/esockd.app.src b/src/esockd.app.src index 2356b4a..4071933 100644 --- a/src/esockd.app.src +++ b/src/esockd.app.src @@ -1,7 +1,7 @@ {application, esockd, [{description, "General Non-blocking TCP/SSL and UDP/DTLS Server"}, {id, "esockd"}, - {vsn, "5.9.3"}, + {vsn, "5.9.4"}, {modules, []}, {registered, []}, {applications, [kernel, stdlib, sasl, ssl]}, diff --git a/src/esockd.appup.src b/src/esockd.appup.src index 7ed0b70..3c5b3c1 100644 --- a/src/esockd.appup.src +++ b/src/esockd.appup.src @@ -1,8 +1,13 @@ -%%-*-: erlang -*- +%%-*- mode: erlang; -*- -{"5.9.3", - [{"5.9.2", +{"5.9.4", + [{"5.9.3", + [ {load_module,esockd_transport,brutal_purge,soft_purge,[]} + ] + }, + {"5.9.2", [ {load_module,esockd_udp,brutal_purge,soft_purge,[]} + , {load_module,esockd_transport,brutal_purge,soft_purge,[]} ] }, {"5.9.1", @@ -23,8 +28,13 @@ }, {<<".*">>, []} ], - [{"5.9.2", + [{"5.9.3", + [ {load_module,esockd_transport,brutal_purge,soft_purge,[]} + ] + }, + {"5.9.2", [ {load_module,esockd_udp,brutal_purge,soft_purge,[]} + , {load_module,esockd_transport,brutal_purge,soft_purge,[]} ] }, {"5.9.1", diff --git a/src/esockd_transport.erl b/src/esockd_transport.erl index c7e3b25..01f84d9 100644 --- a/src/esockd_transport.erl +++ b/src/esockd_transport.erl @@ -345,11 +345,15 @@ shutdown(#proxy_socket{socket = Sock}, How) -> -spec(ssl_upgrade_fun([ssl:ssl_option()]) -> esockd:sock_fun()). ssl_upgrade_fun(SslOpts) -> {Timeout, SslOpts1} = take_handshake_timeout(SslOpts), - {fun ?MODULE:ssl_upgrade/3, [SslOpts1, Timeout]}. + {GCAfterHandshake, SslOpts2} = take_gc_after_handshake(SslOpts1), + {fun ?MODULE:ssl_upgrade/3, [SslOpts2, #{timeout => Timeout, + gc_after_handshake => GCAfterHandshake}]}. -ssl_upgrade(Sock, SslOpts1, Timeout) -> +ssl_upgrade(Sock, SslOpts1, #{timeout := Timeout, + gc_after_handshake := GCAfterHandshake}) -> try do_ssl_handshake(Sock, SslOpts1, Timeout) of {ok, NSock} -> + GCAfterHandshake andalso gc(NSock), {ok, NSock}; {error, Reason} when Reason =:= closed; Reason =:= timeout -> {error, Reason}; @@ -395,6 +399,10 @@ take_handshake_timeout(SslOpts) -> {?SSL_HANDSHAKE_TIMEOUT, SslOpts} end. +take_gc_after_handshake(SslOpts) -> + {proplists:get_bool(gc_after_handshake, SslOpts), + proplists:delete(gc_after_handshake, SslOpts)}. + %% @doc TCP | SSL -> ProxySocket proxy_upgrade_fun(Opts) -> Timeout = proxy_protocol_timeout(Opts), @@ -422,12 +430,28 @@ ensure_ok_or_exit(Fun, Args = [Sock|_]) when is_atom(Fun), is_list(Args) -> end. gc(Sock) when is_port(Sock) -> - ok; + case erlang:port_info(Sock, connected) of + {connected, Pid} -> + erlang:garbage_collect(Pid), + ok; + undefined -> + ok + end; %% Defined in ssl/src/ssl_api.hrl: %% -record(sslsocket, {fd = nil, pid = nil}). gc(#ssl_socket{ssl = {sslsocket, _, Pid}}) when is_pid(Pid) -> - erlang:garbage_collect(Pid); + erlang:garbage_collect(Pid), + ok; +%% In OTP 24+, the last element is a list of PIDs The first is spawned +%% by `ssl_gen_statem:init/1', the second by `tls_sender:init/1`. +gc(#ssl_socket{ssl = {sslsocket, _, Pids}}) when is_list(Pids) -> + lists:foreach( + fun(Pid) when is_pid(Pid) -> + erlang:garbage_collect(Pid); + (_) -> + ok + end, + Pids); gc(#proxy_socket{socket = Sock}) -> gc(Sock); gc(_Sock) -> ok. - diff --git a/test/esockd_transport_SUITE.erl b/test/esockd_transport_SUITE.erl index ee43991..cfa48b3 100644 --- a/test/esockd_transport_SUITE.erl +++ b/test/esockd_transport_SUITE.erl @@ -97,6 +97,17 @@ t_send_ssl(Config) -> ok = esockd_transport:close(#ssl_socket{ssl = SslSock}), ok = esockd:close(echo, 8883). +t_send_ssl_gc_after_handshake(Config) -> + ssl:start(), + SslOpts = [{certfile, esockd_ct:certfile(Config)}, + {keyfile, esockd_ct:keyfile(Config)}, + {gc_after_handshake, true}], + {ok, _} = esockd:open(echo, 8883, [{ssl_options, SslOpts}], {echo_server, start_link, []}), + {ok, SslSock} = ssl:connect({127,0,0,1}, 8883, [], 3000), + ok = esockd_transport:send(#ssl_socket{ssl = SslSock}, <<"Hello">>), + ok = esockd_transport:close(#ssl_socket{ssl = SslSock}), + ok = esockd:close(echo, 8883). + t_send_proxy(_) -> {ok, _} = esockd:open(echo, 5000, [{tcp_options, [binary]}, proxy_protocol, @@ -188,11 +199,16 @@ t_proxy_upgrade_fun(_) -> ?assert(is_function(Fun)). t_ssl_upgrade_fun(_) -> - {Fun, [[], 1000]} = esockd_transport:ssl_upgrade_fun([{handshake_timeout, 1000}]), - ?assert(is_function(Fun)). + {Fun0, [[], #{timeout := 1000, gc_after_handshake := false}]} + = esockd_transport:ssl_upgrade_fun([{handshake_timeout, 1000}]), + ?assert(is_function(Fun0, 3)), + {Fun1, [[], #{timeout := 1000, gc_after_handshake := true}]} + = esockd_transport:ssl_upgrade_fun([{handshake_timeout, 1000}, + {gc_after_handshake, true}]), + ?assert(is_function(Fun1, 3)), + ok. t_fast_close(_) -> {ok, LSock} = esockd_transport:listen(3000, [{reuseaddr, true}]), ok = esockd_transport:fast_close(LSock), ok = esockd_transport:close(LSock). -