Attempt to fix port leak, also fixed clean up of sockets. #1

Merged
merged 1 commit into from Jul 9, 2012
View
2 src/lhttpc_lb.erl
@@ -156,7 +156,7 @@ code_change(_OldVsn, State, _Extra) ->
terminate(_Reason, #state{host=H, port=P, ssl=Ssl, free=Free, clients=Tid}) ->
ets:delete(Tid),
ets:delete(?MODULE,{H,P,Ssl}),
- [lhttpc_sock:close(Socket,Ssl) || Socket <- Free],
+ [lhttpc_sock:close(Socket,Ssl) || {Socket, _TimerRef} <- Free],
ok.
%%%%%%%%%%%%%%%
View
40 src/lhttpc_sock.erl
@@ -59,9 +59,25 @@
-spec connect(host(), integer(), socket_options(), timeout(), boolean()) ->
{ok, socket()} | {error, atom()}.
connect(Host, Port, Options, Timeout, true) ->
- ssl:connect(Host, Port, Options, Timeout);
+ % Avoid port leak with potential race condition in case of timeout
+ Flag = process_flag(trap_exit, true),
+ Res = ssl:connect(Host, Port, Options, Timeout),
+ receive
+ {'EXIT',_Pid,timeout} -> exit(timeout)
+ after 0 ->
+ process_flag(trap_exit, Flag),
+ Res
+ end;
connect(Host, Port, Options, Timeout, false) ->
- gen_tcp:connect(Host, Port, Options, Timeout).
+ % Avoid port leak with potential race condition in case of timeout
+ Flag = process_flag(trap_exit, true),
+ Res = gen_tcp:connect(Host, Port, Options, Timeout),
+ receive
+ {'EXIT',_Pid,timeout} -> exit(timeout)
+ after 0 ->
+ process_flag(trap_exit, Flag),
+ Res
+ end.
%% @spec (Socket, SslFlag) -> {ok, Data} | {error, Reason}
%% Socket = socket()
@@ -154,6 +170,22 @@ setopts(Socket, Options, false) ->
%% @end
-spec close(socket(), boolean()) -> ok | {error, atom()}.
close(Socket, true) ->
- ssl:close(Socket);
+ % Avoid port leak with potential race condition in case of timeout
+ Flag = process_flag(trap_exit, true),
+ Res = ssl:close(Socket),
+ receive
+ {'EXIT',_Pid,timeout} -> exit(timeout)
+ after 0 ->
+ process_flag(trap_exit, Flag),
+ Res
+ end;
close(Socket, false) ->
- gen_tcp:close(Socket).
+ % Avoid port leak with potential race condition in case of timeout
+ Flag = process_flag(trap_exit, true),
+ Res = gen_tcp:close(Socket),
+ receive
+ {'EXIT',_Pid,timeout} -> exit(timeout)
+ after 0 ->
+ process_flag(trap_exit, Flag),
+ Res
+ end.