agent: Handle EWOULDBLOCK when transmitting pseudo-TCP segments
authorPhilip Withnall <philip@tecnocode.co.uk>
Mon, 15 Dec 2014 23:35:13 +0000 (23:35 +0000)
committerPhilip Withnall <philip.withnall@collabora.co.uk>
Wed, 17 Dec 2014 08:30:46 +0000 (08:30 +0000)
The pseudo-TCP code previously didn’t handle EAGAIN or EWOULDBLOCK
errors from the low-level NiceSocket code. This caused pseudo-TCP
connections to be dropped if the transmitting socket ever filled up,
which could cause problems on high bandwidth connections.

Fix the issue by effectively dropping the packet on EWOULDBLOCK. This
will eventually get picked up by the pseudo-TCP recovery mechanism,
retransmitting the packet and throttling the sender. This should
hopefully reduce the system resource usage which caused EWOULDBLOCK in
the first place.

Spotted and debugged by Radosław Kołodziejczyk
<radek.kolodziejczyk@gmail.com>.

https://bugs.freedesktop.org/show_bug.cgi?id=87344

agent/agent.c

index a2fd46d..c0efd76 100644 (file)
@@ -1754,8 +1754,15 @@ pseudo_tcp_socket_write_packet (PseudoTcpSocket *psocket,
           nice_address_get_port (addr));
     }
 
-    if (nice_socket_send (sock, addr, len, buffer))
+    /* Send the segment. nice_socket_send() returns 0 on EWOULDBLOCK; in that
+     * case the segment is not sent on the wire, but we return WR_SUCCESS
+     * anyway. This effectively drops the segment. The pseudo-TCP state machine
+     * will eventually pick up this loss and go into recovery mode, reducing
+     * its transmission rate and, hopefully, the usage of system resources
+     * which caused the EWOULDBLOCK in the first place. */
+    if (nice_socket_send (sock, addr, len, buffer) >= 0) {
       return WR_SUCCESS;
+    }
   } else {
     nice_debug ("%s: WARNING: Failed to send pseudo-TCP packet from agent %p "
         "as no pair has been selected yet.", G_STRFUNC, component->agent);