Skip to content

Commit

Permalink
Attempt at fixing a possible process leak
Browse files Browse the repository at this point in the history
Yoshihiro Tanaka found that when lhttpc:request closes a worker
due to a timeout, it's possible that it happens after the port
is unlinked in prim_inet:close, but before it is properly closed.

This results in orphaned sockets/ports being left hanging in the
ether.

This fix attempts to wrap lhttpc_sock:close commands around a safe
build that should resolve it.

A potential fix would have been to have the manager monitor the
sockets itself, but this wouldn't have worked if the socket is new
and the manager has never seen it before, hence the current fix.
  • Loading branch information
ferd committed Jul 6, 2012
1 parent 5bfddba commit 3cf37fe
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/lhttpc.app.src
Expand Up @@ -29,7 +29,7 @@
%%% @end
{application, lhttpc,
[{description, "Lightweight HTTP Client"},
{vsn, "1.2.7"},
{vsn, "1.2.8"},
{modules, [lhttpc,lhttpc_sup,lhttpc_client,lhttpc_sock,lhttp_lb]},
{registered, [lhttpc_sup]},
{applications, [kernel, stdlib, ssl, crypto]},
Expand Down
26 changes: 24 additions & 2 deletions src/lhttpc_sock.erl
Expand Up @@ -154,6 +154,28 @@ setopts(Socket, Options, false) ->
%% @end
-spec close(socket(), boolean()) -> ok | {error, atom()}.
close(Socket, true) ->
ssl:close(Socket);
%% Safer exiting. Yoshihiro Tanaka from OpenX figured out
%% that we had potential race conditions while closing the
%% socket and timing out. This process flagging aims to
%% wrap some safety around this in case of a 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).
%% Safer exiting. Yoshihiro Tanaka from OpenX figured out
%% that we had potential race conditions while closing the
%% socket and timing out. This process flagging aims to
%% wrap some safety around this in case of a 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.

0 comments on commit 3cf37fe

Please sign in to comment.