From 30978004b33575bb9c1ff45ff8df166792a90f8b Mon Sep 17 00:00:00 2001 From: antirez Date: Wed, 30 Sep 2015 16:24:17 +0200 Subject: redis-cli pipe mode: don't stay in the write loop forever. The code was broken and resulted in redis-cli --pipe to, most of the times, writing everything received in the standard input to the Redis connection socket without ever reading back the replies, until all the content to write was written. This means that Redis had to accumulate all the output in the output buffers of the client, consuming a lot of memory. Fixed thanks to the original report of anomalies in the behavior provided by Twitter user @fsaintjacques. --- src/redis-cli.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/redis-cli.c b/src/redis-cli.c index 825162b81..92e294127 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -1397,6 +1397,7 @@ static void getRDB(void) { * Bulk import (pipe) mode *--------------------------------------------------------------------------- */ +#define PIPEMODE_WRITE_LOOP_MAX_BYTES (128*1024) static void pipeMode(void) { int fd = context->fd; long long errors = 0, replies = 0, obuf_len = 0, obuf_pos = 0; @@ -1473,6 +1474,8 @@ static void pipeMode(void) { /* Handle the writable state: we can send protocol to the server. */ if (mask & AE_WRITABLE) { + ssize_t loop_nwritten = 0; + while(1) { /* Transfer current buffer to server. */ if (obuf_len != 0) { @@ -1489,6 +1492,7 @@ static void pipeMode(void) { } obuf_len -= nwritten; obuf_pos += nwritten; + loop_nwritten += nwritten; if (obuf_len != 0) break; /* Can't accept more data. */ } /* If buffer is empty, load from stdin. */ @@ -1524,7 +1528,8 @@ static void pipeMode(void) { obuf_pos = 0; } } - if (obuf_len == 0 && eof) break; + if ((obuf_len == 0 && eof) || + loop_nwritten > PIPEMODE_WRITE_LOOP_MAX_BYTES) break; } } -- cgit v1.2.1