<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Oct 28, 2014 at 8:46 AM, Holger Weiß <span dir="ltr"><<a href="mailto:holger@zedat.fu-berlin.de" target="_blank">holger@zedat.fu-berlin.de</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Hi there,<br>
<br>
I'm an ejabberd contributor, and we're currently facing the issue that<br>
gen_tcp:send/2 occasionally blocks forever even though a 'send_timeout'<br>
(and 'send_timeout_close') has been specified.¹  This seems to happen<br>
only under rare circumstances, but when it happens, it can crash the VM,<br>
as the process that's stuck in the gen_tcp:send/2 call stops processing<br>
its message queue and therefore eats the available memory, eventually.<br>
<br>
This *only* seems to happen when epoll(7) is used, i.e. when "+K true"<br>
is specified on Linux.  "+K false" makes the issue go away.<br>
<br>
Also, it only happens when the TCP socket is no longer usable.  In the<br>
past, it could occur that an ejabberd process called gen_tcp:send/2 even<br>
though an earlier call returned a failure already.  Since we changed the<br>
code to fix that, the issue is triggered less frequently; and in those<br>
cases where it still *is* triggered, it's obvious from looking at the<br>
details that the socket got closed more or less at the same time.<br>
<br>
The problem is that I'm not able to reproduce this myself.  So far,<br>
we've only been made aware of this issue on two servers, both of them<br>
running in production, and it's only easily reproducible on one of them.<br>
That one is running Erlang 17.1 on a Xen instance (I guess I could ask<br>
the admin to update to 17.3).<br>
<br>
Without code to reproduce the issue, this is probably non-trivial to<br>
debug :-(  At least there's one live system where the issue is usually<br>
triggered multiple times per day.  Any suggestions on how to proceed?<br>
<br>
Thanks, Holger<br>
<br>
¹ According to process_info/1, the current function is prim_inet:send/3.<br></blockquote><div><br></div><div>I've seen this happen when the receiver is not reading from its socket, thus causing the TCP window to close to apply backpressure to the sender, and so Erlang's inet driver fills the kernel's send buffers and then inet_drv fills its own buffers with data to be sent. Once those are all full, and you try to send again, prim_inet:send blocks waiting to receive a message from inet_drv that won't be sent until some send buffer space is freed up due to the receiver reading data from its socket. Under these conditions, netstat will show your connection's kernel buffers to be full and unchanging, and a call to erlang:port_info(Socket, queue_size) will show queued data greater than the default of 8k for that socket. It can sit that way forever until the receiver reads.</div><div><br></div><div>One thing that might help under these conditions is to send data directly via port_command like this:</div><div><br></div><div>    erlang:port_command(Socket, Data, [nosuspend])</div><div><br></div><div>which returns false if the port/socket is busy, but even this doesn't seem to be foolproof, nor does relying on send_timeout. I've seen both work, and in fact both worked as expected in little cases I tried before sending this reply, but I've also seen cases where I expected them to work but they didn't and I couldn't determine why.</div><div><br></div><div>--steve</div></div></div></div>