[erlang-questions] Processes hanging in prim_inet:close_port/1
Brandon Clark
a.brandon.clark@REDACTED
Fri Dec 6 23:07:11 CET 2013
Greetings!
I have an application where, once in a while, processes appear to hang in
prim_inet:close_port/1. I'm not sure what to do with that.
The application uses R16B02.
Here's a sample of the process info for a "stuck" process:
[{current_stacktrace,[{prim_inet,close_port,1,[]},
{inet,tcp_close,1,[{file,"inet.erl"},{line,1422}]},
{proxy_worker,disconnect_endpoint,1,
[{file,"src/proxy_worker.erl"},{line,1082}]},
{proxy_worker,process_chunked_reply,1,
[{file,"src/proxy_worker.erl"},{line,496}]},
{proxy_worker,process_request,2,
[{file,"src/proxy_worker.erl"},{line,100}]},
{proxy_worker,work_request,2,
[{file,"src/proxy_worker.erl"},{line,87}]},
{pool_worker,handle_cast,2,
[{file,"src/pool_worker.erl"},{line,73}]},
{gen_server,handle_msg,5,
[{file,"gen_server.erl"},{line,604}]}]},
{current_function,{prim_inet,close_port,1}},
{initial_call,{proc_lib,init_p,5}},
{status,waiting},
{message_queue_len,1},
{messages,[{tcp_closed,#Port<9492.545567>}]},
{links,[<9492.10266.0>]},
{dictionary,[{'$ancestors',[<9492.10266.0>,<9492.10263.0>,
cellophane_sup,<9492.114.0>]},
{'$initial_call',{pool_worker,init,1}}]},
{trap_exit,true},
{error_handler,error_handler},
{priority,normal},
{group_leader,<9492.113.0>},
{total_heap_size,2586},
{heap_size,2586},
{stack_size,44},
{reductions,4490210},
{garbage_collection,[{min_bin_vheap_size,46422},
{min_heap_size,233},
{fullsweep_after,0},
{minor_gcs,0}]},
{suspending,[]}]}]
Apparently, this condition occurs -- intermittently -- when the client (the
process described above) and the server (a different app and platform)
decide to close their socket connection at about the same time. Notice the
tcp_closed message in the inbox.
The socket in question is in {active, once} mode.
The {status,waiting} and {trap_exit, true} suggest to me that the process
is stuck in the receive at line 210 of prim_inet:
188 close_port(S) ->
189 case erlang:process_info(self(), trap_exit) of
190 {trap_exit,true} ->
191 %% Ensure exit message and consume it
192 link(S),
193 %% This is still not a perfect solution.
194 %%
195 %% The problem is to close the port and consume any exit
196 %% message while not knowing if this process traps exit
197 %% nor if this process has a link to the port. Here we
198 %% just knows that this process traps exit.
199 %%
200 %% If we right here get killed for some reason that exit
201 %% signal will propagate to the port and onwards to anyone
202 %% that is linked to the port. E.g when we close a socket
203 %% that is not ours.
204 %%
205 %% The problem can be solved with lists:member on our link
206 %% list but we deem that as potentially too expensive. We
207 %% need an is_linked/1 function or guard, or we need
208 %% a port_close function that can atomically unlink...
209 catch erlang:port_close(S),
210 receive {'EXIT',S,_} -> ok end;
211 {trap_exit,false} ->
212 catch erlang:port_close(S),
213 ok
214 end.
But now I'm speculating. I'm in over my head, here.
Any suggestions on how to clear up these stuck processes would be greatly
appreciated!
~BC
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20131206/ff388b60/attachment.htm>
More information about the erlang-questions
mailing list