From: Andre Noll Date: Mon, 6 Aug 2007 14:09:28 +0000 (+0200) Subject: dccp sender: Keep polling until an entry becomes free (Gerrit Renker). X-Git-Tag: v0.2.17~38^2 X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=commitdiff_plain;h=7f2f826603c955d35d50d6ab2a6ed48a3bc24ab8;ds=sidebyside dccp sender: Keep polling until an entry becomes free (Gerrit Renker). 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. --- diff --git a/NEWS b/NEWS index 03045da3..33c17e1e 100644 --- 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" diff --git a/dccp_send.c b/dccp_send.c index 27343fbc..bdc7681e 100644 --- a/dccp_send.c +++ b/dccp_send.c @@ -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,