c2s process blocked in gen_tcp send

Generally in ejabberd , i route message to client process, send to tcp socket via this function. And it works well most time.

Module ejabberd_c2s.erl

send_text(StateData, Text) when StateData#state.mgmt_state == active ->
    catch ?INFO_MSG("Send XML on stream = ~ts", [Text]),
    case catch (StateData#state.sockmod):send(StateData#state.socket, Text) of
      {'EXIT', _} ->
  (StateData#state.sockmod):close(StateData#state.socket),
  error;
      _ ->
  ok
    end;

But in some cases the c2s pid blocked on gen_tcp:send like this

erlang:process_info(pid(0,8353,11)).
[{current_function,{prim_inet,send,3}},
{initial_call,{proc_lib,init_p,5}},
{status,waiting},
{message_queue_len,96},
{messages ...}
...

Most cases happened when user's network status not so good, the receiver process should send 2 messages to c2s pid , and c2s would terminate session or wait for resume
{'$gen_event',closed}
{'DOWN',#Ref<0.0.1201.250595>,process,<0.19617.245>,normal}

I printed message queue in the c2s process, the 2 msg are in the queue, waiting to be handled. Unfortunately,
the queue does not move any more becasue the process had blocked before handling these messages, as described above, stacked at prim_inet:send/3 when tring to do gen_tcp:send/2.
The queue grows very large after days, and ejabberd crahes when the process asking for more memory.

prim_inet:send/3 source code :

send(S, Data, OptList) when is_port(S), is_list(OptList) ->
    ?DBG_FORMAT("prim_inet:send(~p, ~p)~n", [S,Data]),
    try erlang:port_command(S, Data, OptList) of
false -> % Port busy and nosuspend option passed
    ?DBG_FORMAT("prim_inet:send() -> {error,busy}~n", []),
    {error,busy};
true ->
    receive
{inet_reply,S,Status} ->
    ?DBG_FORMAT("prim_inet:send() -> ~p~n", [Status]),
    Status
    end
    catch
error:_Error ->
    ?DBG_FORMAT("prim_inet:send() -> {error,einval}~n", []),
     {error,einval}
    end.

it seems the port driver did not reply {inet_reply,S,Status} after erlang:port_command(S, Data, OptList) .
Can anyone explain this?

Syndicate content