From a8e9515a46d47da1af3e528169f70afbcdb5566b Mon Sep 17 00:00:00 2001 From: Trond Norbye Date: Wed, 5 Sep 2012 22:24:59 +0200 Subject: Fix problem with "Failed to write, and not due to blocking" It has been observed in strace output that we sometimes call sendmsg with a request of sending 0 bytes.. The kernel obeys our request and send 0 bytes and we treat that as an error. --- memcached.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/memcached.c b/memcached.c index 23b771a..faa4033 100644 --- a/memcached.c +++ b/memcached.c @@ -700,6 +700,10 @@ static int add_iov(conn *c, const void *buf, int len) { assert(c != NULL); + if (len == 0) { + return 0; + } + do { m = &c->msglist[c->msgused - 1]; @@ -1001,9 +1005,7 @@ static void write_bin_error(conn *c, protocol_binary_response_status err, int sw len = strlen(errstr); add_bin_header(c, err, 0, 0, len); - if (len > 0) { - add_iov(c, errstr, len); - } + add_iov(c, errstr, len); conn_set_state(c, conn_mwrite); if(swallow > 0) { c->sbytes = swallow; @@ -1018,9 +1020,7 @@ static void write_bin_response(conn *c, void *d, int hlen, int keylen, int dlen) if (!c->noreply || c->cmd == PROTOCOL_BINARY_CMD_GET || c->cmd == PROTOCOL_BINARY_CMD_GETK) { add_bin_header(c, 0, hlen, keylen, dlen); - if(dlen > 0) { - add_iov(c, d, dlen); - } + add_iov(c, d, dlen); conn_set_state(c, conn_mwrite); c->write_and_go = conn_new_cmd; } else { @@ -1743,9 +1743,7 @@ static void process_bin_complete_sasl_auth(conn *c) { break; case SASL_CONTINUE: add_bin_header(c, PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE, 0, 0, outlen); - if(outlen > 0) { - add_iov(c, out, outlen); - } + add_iov(c, out, outlen); conn_set_state(c, conn_mwrite); c->write_and_go = conn_new_cmd; break; @@ -3680,11 +3678,12 @@ void do_accept_new_conns(const bool do_accept) { static enum transmit_result transmit(conn *c) { assert(c != NULL); - if (c->msgcurr < c->msgused && + while (c->msgcurr < c->msgused && c->msglist[c->msgcurr].msg_iovlen == 0) { /* Finished writing the current msg; advance to the next. */ c->msgcurr++; } + if (c->msgcurr < c->msgused) { ssize_t res; struct msghdr *m = &c->msglist[c->msgcurr]; -- cgit v1.2.1