summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrond Norbye <trond.norbye@gmail.com>2012-09-05 22:24:59 +0200
committerTrond Norbye <trond.norbye@gmail.com>2012-09-05 22:24:59 +0200
commita8e9515a46d47da1af3e528169f70afbcdb5566b (patch)
treefffb8f70488a5574ec4fcdc050b784e2930464bb
parentfa24ccfb9ff097a86915f34523fdba944fe5474a (diff)
downloadmemcached-failed-to-write-fix.tar.gz
Fix problem with "Failed to write, and not due to blocking"failed-to-write-fix
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.
-rw-r--r--memcached.c19
1 files 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];