From 740c41c0f26f0773a11c7121dc2aff1fdb34f9b1 Mon Sep 17 00:00:00 2001 From: Mikhail Fesenko Date: Wed, 7 Jul 2021 08:26:26 +0300 Subject: [PATCH] Direct redis-cli repl prints to stderr, because --rdb can print to stdout. fflush stdout after responses (#9136) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. redis-cli can output --rdb data to stdout but redis-cli also write some messages to stdout which will mess up the rdb. 2. Make redis-cli flush stdout when printing a reply This was needed in order to fix a hung in redis-cli test that uses --replica. Note that printf does flush when there's a newline, but fwrite does not. 3. fix the redis-cli --replica test which used to pass previously because it didn't really care what it read, and because redis-cli used printf to print these other things to stdout. 4. improve redis-cli --replica test to run with both diskless and disk-based. Co-authored-by: Oran Agra Co-authored-by: Viktor Söderqvist (cherry picked from commit 1eb4baa5b8e76adc337ae9fab49acc2585a0cdd0) --- src/redis-cli.c | 5 +++-- tests/integration/redis-cli.tcl | 28 ++++++++++++++++++++++------ 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/redis-cli.c b/src/redis-cli.c index d4d5e7459..06ccf1563 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -1312,6 +1312,7 @@ static int cliReadReply(int output_raw_strings) { if (output) { out = cliFormatReply(reply, config.output, output_raw_strings); fwrite(out,sdslen(out),1,stdout); + fflush(stdout); sdsfree(out); } freeReplyObject(reply); @@ -6990,7 +6991,7 @@ static void latencyDistMode(void) { #define RDB_EOF_MARK_SIZE 40 void sendReplconf(const char* arg1, const char* arg2) { - printf("sending REPLCONF %s %s\n", arg1, arg2); + fprintf(stderr, "sending REPLCONF %s %s\n", arg1, arg2); redisReply *reply = redisCommand(context, "REPLCONF %s %s", arg1, arg2); /* Handle any error conditions */ @@ -7050,7 +7051,7 @@ unsigned long long sendSync(redisContext *c, char *out_eof) { } *p = '\0'; if (buf[0] == '-') { - printf("SYNC with master failed: %s\n", buf); + fprintf(stderr, "SYNC with master failed: %s\n", buf); exit(1); } if (strncmp(buf+1,"EOF:",4) == 0 && strlen(buf+5) >= RDB_EOF_MARK_SIZE) { diff --git a/tests/integration/redis-cli.tcl b/tests/integration/redis-cli.tcl index 7e8b41fca..d58229bb4 100644 --- a/tests/integration/redis-cli.tcl +++ b/tests/integration/redis-cli.tcl @@ -283,9 +283,9 @@ start_server {tags {"cli"}} { assert_equal {key:2} [run_cli --scan --quoted-pattern {"*:\x32"}] } - test "Connecting as a replica" { + proc test_redis_cli_repl {} { set fd [open_cli "--replica"] - wait_for_condition 500 500 { + wait_for_condition 500 100 { [string match {*slave0:*state=online*} [r info]] } else { fail "redis-cli --replica did not connect" @@ -294,14 +294,30 @@ start_server {tags {"cli"}} { for {set i 0} {$i < 100} {incr i} { r set test-key test-value-$i } - r client kill type slave - catch { - assert_match {*SET*key-a*} [read_cli $fd] + + wait_for_condition 500 100 { + [string match {*test-value-99*} [read_cli $fd]] + } else { + fail "redis-cli --replica didn't read commands" } - close_cli $fd + fconfigure $fd -blocking true + r client kill type slave + catch { close_cli $fd } err + assert_match {*Server closed the connection*} $err } + test "Connecting as a replica" { + # Disk-based master + assert_match "OK" [r config set repl-diskless-sync no] + test_redis_cli_repl + + # Disk-less master + assert_match "OK" [r config set repl-diskless-sync yes] + assert_match "OK" [r config set repl-diskless-sync-delay 0] + test_redis_cli_repl + } {} + test "Piping raw protocol" { set cmds [tmpfile "cli_cmds"] set cmds_fd [open $cmds "w"]