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:27:19 +0200
commit30978004b33575bb9c1ff45ff8df166792a90f8b (patch)
treebf95bbcc7076d0ae59e3d88765196b6b4beffe90
parent652e662d1a1d994e5cf12700d4bf7b1dbe5a1dc8 (diff)
downloadredis-30978004b33575bb9c1ff45ff8df166792a90f8b.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 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;
}
}