From 7f2f826603c955d35d50d6ab2a6ed48a3bc24ab8 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Mon, 6 Aug 2007 16:09:28 +0200 Subject: [PATCH] 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. --- NEWS | 2 ++ dccp_send.c | 39 +++++++++++++++++---------------------- 2 files changed, 19 insertions(+), 22 deletions(-) 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, -- 2.39.5