dccp sender: Keep polling until an entry becomes free (Gerrit Renker).
authorAndre Noll <maan@systemlinux.org>
Mon, 6 Aug 2007 14:09:28 +0000 (16:09 +0200)
committerAndre Noll <maan@systemlinux.org>
Mon, 6 Aug 2007 14:09:28 +0000 (16:09 +0200)
If write() on the dccp fd fails with EAGAIN, the current code retries
100 times and then gives up, returning -E_DCCP_WRITE which causes a
shutdown of the dccp connection.

CCID3 has a sending wait queue which fills up and is emptied
asynchronously. The EAGAIN case means that there is currently no space
in the wait queue, but this can change at any moment and is thus not
an error condition. So keep polling until an entry becomes free.

NEWS
dccp_send.c

diff --git a/NEWS b/NEWS
index 03045da..33c17e1 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -15,6 +15,8 @@ the 0.2.x series if no serious bugs show up after the release.
        - update to gengetopt-2.20.
        - autoconf: extend checks for headers, library functions and
          compiler characteristics.
+       - dccp sender: Keep polling until an entry becomes free if write()
+         returns EAGAIN (Gerrit Renker).
 
 --------------------------------------
 0.2.16 (2007-04-05) "neural discharge"
index 27343fb..bdc7681 100644 (file)
@@ -108,31 +108,26 @@ static void dccp_shutdown_client(struct dccp_client *dc)
        free(dc);
 }
 
-/** give up if write would block that many times */
-#define DCCP_WRITE_RETRIES 100
-
 static int dccp_write(int fd, const char *buf, size_t len)
 {
-       size_t size, written = 0;
-       int ret, retries = 0;
-again:
-       size = PARA_MIN(1024, len - written);
-       ret = write(fd, buf + written, size);
-       if (ret < 0) {
-               if (errno != EAGAIN || retries++ > DCCP_WRITE_RETRIES)
-                       goto err_out;
-               PARA_DEBUG_LOG("EAGAIN #%d@%zd/%zd\n", retries, written, len);
-               goto again;
+       size_t written = 0;
+       int ret = 0;
+
+       while (written < len) {
+               ret = write(fd, buf + written, PARA_MIN(1024, len - written));
+               /*
+                * Error handling: CCID3 has a sending wait queue which fills up and is
+                * emptied asynchronously. The EAGAIN case means that there is currently
+                * no space in the wait queue, but this can change at any moment and is
+                * thus not an error condition. Keep polling until an entry becomes free.
+                */
+               if (ret < 0 && errno == EAGAIN)
+                       continue;
+               if (ret < 0)
+                       return -E_DCCP_WRITE;
+               written += ret;
        }
-       retries = 0;
-       written += ret;
-       if (written >= len)
-               return written;
-       ret = write_ok(fd);
-       if (ret > 0)
-               goto again;
-err_out:
-       return -E_DCCP_WRITE;
+       return written;
 }
 
 static void dccp_send(long unsigned current_chunk,