From 2186c2e945a54941a7e4e63ce502db761e18afbf Mon Sep 17 00:00:00 2001 From: Mikhail Fesenko Date: Wed, 30 Jun 2021 16:49:54 +0300 Subject: [PATCH] redis-cli --rdb: fix broken fsync/ftruncate for stdout (#9135) A change in redis 6.2 caused redis-cli --rdb that's directed to stdout to fail because fsync fails. This commit avoids doing ftruncate (fails with a warning) and fsync (fails with an error) when the output file is `-`, and adds the missing documentation that `-` means stdout. Co-authored-by: Oran Agra Co-authored-by: Wang Yuan (cherry picked from commit 74fe15b3602ed7c003b5c53e45e31f7aa6d4a86f) --- src/redis-cli.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/redis-cli.c b/src/redis-cli.c index 8e049f186..d4d5e7459 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -1896,6 +1896,7 @@ static void usage(void) { " --lru-test Simulate a cache workload with an 80-20 distribution.\n" " --replica Simulate a replica showing commands received from the master.\n" " --rdb Transfer an RDB dump from remote server to local file.\n" +" Use filename of \"-\" to write to stdout.\n" " --pipe Transfer raw Redis protocol from stdin to server.\n" " --pipe-timeout In --pipe mode, abort with error if after sending all data.\n" " no reply is received within seconds.\n" @@ -7154,8 +7155,9 @@ static void getRDB(clusterManagerNode *node) { payload, filename); } + int write_to_stdout = !strcmp(filename,"-"); /* Write to file. */ - if (!strcmp(filename,"-")) { + if (write_to_stdout) { fd = STDOUT_FILENO; } else { fd = open(filename, O_CREAT|O_WRONLY, 0644); @@ -7197,7 +7199,7 @@ static void getRDB(clusterManagerNode *node) { } if (usemark) { payload = ULLONG_MAX - payload - RDB_EOF_MARK_SIZE; - if (ftruncate(fd, payload) == -1) + if (!write_to_stdout && ftruncate(fd, payload) == -1) fprintf(stderr,"ftruncate failed: %s.\n", strerror(errno)); fprintf(stderr,"Transfer finished with success after %llu bytes\n", payload); } else { @@ -7206,7 +7208,7 @@ static void getRDB(clusterManagerNode *node) { redisFree(s); /* Close the connection ASAP as fsync() may take time. */ if (node) node->context = NULL; - if (fsync(fd) == -1) { + if (!write_to_stdout && fsync(fd) == -1) { fprintf(stderr,"Fail to fsync '%s': %s\n", filename, strerror(errno)); exit(1); }