git » nmdb » commit f16e9e0

Try harder to send() when we get EAGAIN.

author Alberto Bertogli
2007-07-30 21:27:32 UTC
committer Alberto Bertogli
2007-07-30 21:27:32 UTC
parent 1f3b3f78775582207cfe4ff186b65fb0f032f6f0

Try harder to send() when we get EAGAIN.

With big packets, the receiver window might get exhausted and send()
would block, but as the fd is set in non-blocking mode, it returns
EAGAIN. This patch retries when send() fails in this way.

The proper way to fix this would be to add an event so we get notified
when the fd is available for writing, and retry the send; but this is
complex so leave it for when it's really needed.

Signed-off-by: Alberto Bertogli <albertito@gmail.com>

nmdb/tcp.c +31 -5

diff --git a/nmdb/tcp.c b/nmdb/tcp.c
index 7c86a99..9d22ba0 100644
--- a/nmdb/tcp.c
+++ b/nmdb/tcp.c
@@ -109,16 +109,42 @@ static void rep_send_error(const struct req_info *req, const unsigned int code)
 static int rep_send(const struct req_info *req, const unsigned char *buf,
 		const size_t size)
 {
-	int rv;
+	ssize_t rv, c;
 
 	if (settings.passive)
 		return 1;
 
-	rv = send(req->fd, buf, size, 0);
-	if (rv < 0) {
-		rep_send_error(req, ERR_SEND);
-		return 0;
+	c = 0;
+	while (c < size) {
+		rv = send(req->fd, buf + c, size - c, 0);
+
+		if (rv == size) {
+			return 1;
+		} else if (rv < 0) {
+			if (errno != EAGAIN || errno != EWOULDBLOCK) {
+				rep_send_error(req, ERR_SEND);
+				return 0;
+			} else {
+				/* With big packets, the receiver window might
+				 * get exhausted and send() would block, but
+				 * as the fd is set in non-blocking mode, it
+				 * returns EAGAIN. This makes us to retry when
+				 * send() fails in this way.
+				 *
+				 * The proper way to fix this would be to add
+				 * an event so we get notified when the fd is
+				 * available for writing, and retry the send;
+				 * but this is complex so leave it for when
+				 * it's really needed. */
+				continue;
+			}
+		} else if (rv == 0) {
+			return 1;
+		}
+
+		c += rv;
 	}
+
 	return 1;
 }