summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2015-09-30 16:24:17 +0200
committerantirez <antirez@gmail.com>2015-09-30 16:24:21 +0200
commitd1b6a17d1ed64c919d55a27ea780e973196a5e98 (patch)
tree59f3be8615372a1030b2d103a686fd6bc435d8bc
parent622366aa74e8584a5a2ba9da8461432d3200ddb9 (diff)
downloadredis-d1b6a17d1ed64c919d55a27ea780e973196a5e98.tar.gz
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.
-rw-r--r--src/redis-cli.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/src/redis-cli.c b/src/redis-cli.c
index 88f39a6e9..7c086cfb4 100644
--- a/src/redis-cli.c
+++ b/src/redis-cli.c
@@ -1399,6 +1399,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;
@@ -1475,6 +1476,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) {
@@ -1491,6 +1494,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. */
@@ -1526,7 +1530,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;
}
}