gen_udp:send/4

Mikael Pettersson mikpelinux@REDACTED
Fri Dec 6 21:00:31 CET 2019


On Thu, Dec 5, 2019 at 5:39 PM Steven <mailparmalat@REDACTED> wrote:
>
> Hi,
>
> We have a situation where gen_udp:send/4 does not return ok and it just hangs and the process is waiting indefinitely.
>
> e.g.
>  {current_function,{prim_inet,sendto,4}},
>  {initial_call,{proc_lib,init_p,5}},
>  {status,running},
>  {message_queue_len,15363062},
>
> The send buffer size on the socket is around 200KB.
>
> 3> inet:getopts(S, [sndbuf]).
> {ok,[{sndbuf,212992}]}
>
> The UDP socket doesn't receive any incoming packets so it is used for sending only. Running R21-3 with redhat 7.5. Would like to ask the group under which conditions will the port not come back with inet_reply? I assume if the sndbuf is full then it should come back with enobufs or some sort but it should be quick enough to flush the sndbuf to interface.
>
> In prim_inet:sendTo/4, it always expect inet reply from OS but it never comes and never times out.
>
> try erlang:port_command(S, PortCommandData) of
>                         true ->
>                             receive
>                                 {inet_reply,S,Reply} ->
>                                     ?DBG_FORMAT(
>                                        "prim_inet:sendto() -> ~p~n", [Reply]),
>                                     Reply
>                             end
>                     catch
>
> Thanks

I believe a (or the) problem is that the selective-receive in
prim_inet:sendto/4 doesn't use the ref trick, therefore it has to scan
the entire 15+ million entry message queue of the sender process
looking for that inet_reply message.  That is going to be very slow.
(Furthermore there are other performance penalties associated with
having very long message queues, see
erlang:process_flag(message_queue_data, off_heap) for one possible
remedy.)

It would be nice if the return signalling from calling port_command
could be fixed to either enable the ref trick or to not use messages
at all, but until that is the case, you know that making these calls
while having a long message queue is going to be expensive.  We've
found that it's often useful to offload such calls to temporary helper
processes, that by construction have very short message queues.  (The
signalling between the original process and the helper should of
course use the ref trick, this is non-trivial to get right.)



More information about the erlang-questions mailing list