1、现象
游戏服务器与多个客户端建立连接,socket设置参数如下[binary, {packet, 4}, {active, 0}, {reuseaddr, true}, {nodelay, false}, {packet_size, 4096}, {delay_send, true}, {send_timeout, 5000}, {keepalive, true}, {exit_on_close, true}],其中绝大多数socket可以正常通信,一两个通信异常,表现为服务端无法发送消息。此时,查看socket宿主进程状态,进程的消息列表堆积,堆栈在prim_inet:close_pend_loop/2处死循环。
2、查找过程
从进程的堆栈来看,进程执行到了gen_tcp:close/1,进入关闭流程,gen_tcp:close/1调用inet:tcp_close/1,最后执行prim_inet:close/1,其中prim模块部分代码如下
close(S) when is_port(S) ->
case subscribe(S, [subs_empty_out_q]) of
{ok, [{subs_empty_out_q,N}]} when N > 0 ->
close_pend_loop(S, N); %% wait for pending output to be sent
_ ->
close_port(S)
end.
close_pend_loop(S, N) ->
receive
{empty_out_q,S} ->
close_port(S)