From bbc1cd0bd9cb50e0734a98d066ccc7d0171fc652 Mon Sep 17 00:00:00 2001 From: Matt Stancliff Date: Fri, 28 Mar 2014 23:08:56 -0400 Subject: [PATCH 01/59] redis-cli: Re-attach selected DB after auth Previously, if you did SELECT then AUTH, redis-cli would show your SELECT'd db even though it didn't happen. Note: running into this situation is a (hopefully) very limited used case of people using multiple DBs and AUTH all at the same time. Fixes antirez#1639 --- src/redis-cli.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/redis-cli.c b/src/redis-cli.c index 907e62b7..8c3e013e 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -320,8 +320,10 @@ static int cliSelect() { reply = redisCommand(context,"SELECT %d",config.dbnum); if (reply != NULL) { + int result = REDIS_OK; + if (reply->type == REDIS_REPLY_ERROR) result = REDIS_ERR; freeReplyObject(reply); - return REDIS_OK; + return result; } return REDIS_ERR; } @@ -650,6 +652,8 @@ static int cliSendCommand(int argc, char **argv, int repeat) { if (!strcasecmp(command,"select") && argc == 2) { config.dbnum = atoi(argv[1]); cliRefreshPrompt(); + } else if (!strcasecmp(command,"auth") && argc == 2) { + cliSelect(); } } if (config.interval) usleep(config.interval); From 0042fb0eb09aceb279f073d84bbc05068ea5e3ff Mon Sep 17 00:00:00 2001 From: Matt Stancliff Date: Fri, 1 Aug 2014 11:44:28 -0400 Subject: [PATCH 02/59] redis-cli: stop showing incorrectly selected DB Previously redis-cli would happily show "-1" or "99999" as valid DB choices. Now, if the SELECT call returned an error, we don't update the DB number in the CLI. Inspired by @anupshendkar in #1313 Fixes #566, #1313 --- 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 8c3e013e..28d3e0cd 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -94,6 +94,7 @@ static struct config { sds mb_delim; char prompt[128]; char *eval; + int last_cmd_type; } config; static volatile sig_atomic_t force_cancel_loop = 0; @@ -131,7 +132,7 @@ static void cliRefreshPrompt(void) { strchr(config.hostip,':') ? "[%s]:%d" : "%s:%d", config.hostip, config.hostport); /* Add [dbnum] if needed */ - if (config.dbnum != 0) + if (config.dbnum != 0 && config.last_cmd_type != REDIS_REPLY_ERROR) len += snprintf(config.prompt+len,sizeof(config.prompt)-len,"[%d]", config.dbnum); snprintf(config.prompt+len,sizeof(config.prompt)-len,"> "); @@ -532,6 +533,8 @@ static int cliReadReply(int output_raw_strings) { reply = (redisReply*)_reply; + config.last_cmd_type = reply->type; + /* Check if we need to connect to a different node and reissue the * request. */ if (config.cluster_mode && reply->type == REDIS_REPLY_ERROR && @@ -1887,6 +1890,8 @@ int main(int argc, char **argv) { config.stdinarg = 0; config.auth = NULL; config.eval = NULL; + config.last_cmd_type = -1; + if (!isatty(fileno(stdout)) && (getenv("FAKETTY") == NULL)) config.output = OUTPUT_RAW; else From 426553164d6807e67999101cec95d2afb7aaa3d7 Mon Sep 17 00:00:00 2001 From: Matt Stancliff Date: Fri, 1 Aug 2014 12:05:04 -0400 Subject: [PATCH 03/59] redis-cli: Add --no-raw option Some people need formatted output even when they have no interactive tty. Fixes #760 --- src/redis-cli.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/redis-cli.c b/src/redis-cli.c index 28d3e0cd..a9633c07 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -731,6 +731,8 @@ static int parseOptions(int argc, char **argv) { config.auth = argv[++i]; } else if (!strcmp(argv[i],"--raw")) { config.output = OUTPUT_RAW; + } else if (!strcmp(argv[i],"--no-raw")) { + config.output = OUTPUT_STANDARD; } else if (!strcmp(argv[i],"--csv")) { config.output = OUTPUT_CSV; } else if (!strcmp(argv[i],"--latency")) { @@ -821,6 +823,7 @@ static void usage() { " -c Enable cluster mode (follow -ASK and -MOVED redirections).\n" " --raw Use raw formatting for replies (default when STDOUT is\n" " not a tty).\n" +" --no-raw Force formatted output even when STDOUT is not a tty.\n" " --csv Output in CSV format.\n" " --latency Enter a special mode continuously sampling latency.\n" " --latency-history Like --latency but tracking latency changes over time.\n" From 009cabf1031db42271a1e05980965a129cbbfe1d Mon Sep 17 00:00:00 2001 From: siahl Date: Tue, 29 Jul 2014 16:39:37 -0500 Subject: [PATCH 04/59] Add support for compiling on AIX Closes #1900 --- deps/hiredis/fmacros.h | 4 ++++ deps/hiredis/net.h | 2 +- src/Makefile | 8 +++++++- src/anet.h | 6 +++++- src/fmacros.h | 4 ++++ src/redis.h | 5 +++++ 6 files changed, 26 insertions(+), 3 deletions(-) diff --git a/deps/hiredis/fmacros.h b/deps/hiredis/fmacros.h index 9e5fec0c..6a41aa17 100644 --- a/deps/hiredis/fmacros.h +++ b/deps/hiredis/fmacros.h @@ -5,6 +5,10 @@ #define _BSD_SOURCE #endif +#if defined(_AIX) +#define _ALL_SOURCE +#endif + #if defined(__sun__) #define _POSIX_C_SOURCE 200112L #elif defined(__linux__) || defined(__OpenBSD__) || defined(__NetBSD__) diff --git a/deps/hiredis/net.h b/deps/hiredis/net.h index 5e742f57..3763ab08 100644 --- a/deps/hiredis/net.h +++ b/deps/hiredis/net.h @@ -35,7 +35,7 @@ #include "hiredis.h" -#if defined(__sun) +#if defined(__sun) || defined(_AIX) #define AF_LOCAL AF_UNIX #endif diff --git a/src/Makefile b/src/Makefile index 4ccc6d36..901104b2 100644 --- a/src/Makefile +++ b/src/Makefile @@ -62,13 +62,19 @@ ifeq ($(uname_S),SunOS) else ifeq ($(uname_S),Darwin) # Darwin (nothing to do) +else +ifeq ($(uname_S),AIX) + # AIX + FINAL_LDFLAGS+= -Wl,-bexpall + FINAL_LIBS+= -pthread -lcrypt -lbsd + else # All the other OSes (notably Linux) FINAL_LDFLAGS+= -rdynamic FINAL_LIBS+= -pthread endif endif - +endif # Include paths to dependencies FINAL_CFLAGS+= -I../deps/hiredis -I../deps/linenoise -I../deps/lua/src diff --git a/src/anet.h b/src/anet.h index c4659cd3..5191c4b6 100644 --- a/src/anet.h +++ b/src/anet.h @@ -39,10 +39,14 @@ #define ANET_NONE 0 #define ANET_IP_ONLY (1<<0) -#if defined(__sun) +#if defined(__sun) || defined(_AIX) #define AF_LOCAL AF_UNIX #endif +#ifdef _AIX +#undef ip_len +#endif + int anetTcpConnect(char *err, char *addr, int port); int anetTcpNonBlockConnect(char *err, char *addr, int port); int anetTcpNonBlockBindConnect(char *err, char *addr, int port, char *source_addr); diff --git a/src/fmacros.h b/src/fmacros.h index 44e378a6..e49735ce 100644 --- a/src/fmacros.h +++ b/src/fmacros.h @@ -36,6 +36,10 @@ #define _GNU_SOURCE #endif +#if defined(_AIX) +#define _ALL_SOURCE +#endif + #if defined(__linux__) || defined(__OpenBSD__) #define _XOPEN_SOURCE 700 /* diff --git a/src/redis.h b/src/redis.h index d2b00bff..b049dbee 100644 --- a/src/redis.h +++ b/src/redis.h @@ -626,6 +626,11 @@ typedef struct redisOpArray { struct clusterState; +#ifdef _AIX +#undef hz +#endif + + struct redisServer { /* General */ pid_t pid; /* Main process pid. */ From 9756f61fda6397da0c57bbe353fc0d144a51aaea Mon Sep 17 00:00:00 2001 From: antirez Date: Thu, 7 Aug 2014 12:14:21 +0200 Subject: [PATCH 05/59] Clarify AIX "#undef hz". --- src/redis.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/redis.h b/src/redis.h index b049dbee..2cf96028 100644 --- a/src/redis.h +++ b/src/redis.h @@ -626,11 +626,12 @@ typedef struct redisOpArray { struct clusterState; +/* AIX defines hz to __hz, we don't use this define and in order to allow + * Redis build on AIX we need to undef it. */ #ifdef _AIX #undef hz #endif - struct redisServer { /* General */ pid_t pid; /* Main process pid. */ From 5b3930655fc8aa68d7cd7ae58b32ff8874476e30 Mon Sep 17 00:00:00 2001 From: Wei Jin Date: Mon, 12 May 2014 20:55:54 +0800 Subject: [PATCH 06/59] Remove redundant else/return block Fixes #1741 --- src/t_zset.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/t_zset.c b/src/t_zset.c index 20ef62e2..d3c7214b 100644 --- a/src/t_zset.c +++ b/src/t_zset.c @@ -205,8 +205,6 @@ int zslDelete(zskiplist *zsl, double score, robj *obj) { zslDeleteNode(zsl, x, update); zslFreeNode(x); return 1; - } else { - return 0; /* not found */ } return 0; /* not found */ } From 05676c5d1614ad894a1ff77d941b83732739046e Mon Sep 17 00:00:00 2001 From: Jan-Erik Rediger Date: Fri, 23 May 2014 00:26:40 +0200 Subject: [PATCH 07/59] redis-cli: fix latency result output (Cleaned up a little by @mattsta) Closes #1774 --- src/redis-cli.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/redis-cli.c b/src/redis-cli.c index a9633c07..89afbbcb 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -1850,11 +1850,15 @@ static void intrinsicLatencyMode(void) { printf("Max latency so far: %lld microseconds.\n", max_latency); } + double avg_us = (double)run_time/runs; + double avg_ns = avg_us * 10e3; if (force_cancel_loop || end > test_end) { - printf("\n%lld total runs (avg %lld microseconds per run).\n", - runs, run_time/runs); - printf("Worst run took %.02fx times the average.\n", - (double) max_latency / (run_time/runs)); + printf("\n%lld total runs " + "(avg latency: " + "%.4f microseconds / %.2f nanoseconds per run).\n", + runs, avg_us, avg_ns); + printf("Worst run took %.0fx longer than the average latency.\n", + max_latency / avg_us); exit(0); } } From 1a5e5b6bd44eb106dcb7114a8f22dda4b475238d Mon Sep 17 00:00:00 2001 From: kingsumos Date: Mon, 9 Jun 2014 15:32:27 -0300 Subject: [PATCH 08/59] cluster: fix node connection memory leak Cluster leaks memory while connecting due to missing freeaddrinfo() (Commit modified by @antirez. The freeaddrinfo() call was misplaced so in case of no address was bound, the memory leak was still there). Closes #1801 --- src/anet.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/anet.c b/src/anet.c index 87cc3ea2..c053ccf8 100644 --- a/src/anet.c +++ b/src/anet.c @@ -262,7 +262,8 @@ static int anetTcpGenericConnect(char *err, char *addr, int port, if (source_addr) { int bound = 0; /* Using getaddrinfo saves us from self-determining IPv4 vs IPv6 */ - if ((rv = getaddrinfo(source_addr, NULL, &hints, &bservinfo)) != 0) { + if ((rv = getaddrinfo(source_addr, NULL, &hints, &bservinfo)) != 0) + { anetSetError(err, "%s", gai_strerror(rv)); goto end; } @@ -272,6 +273,7 @@ static int anetTcpGenericConnect(char *err, char *addr, int port, break; } } + freeaddrinfo(bservinfo); if (!bound) { anetSetError(err, "bind: %s", strerror(errno)); goto end; From f17f8521f005321d3e163ed83ec2fa9f1b925b0f Mon Sep 17 00:00:00 2001 From: Matt Stancliff Date: Sat, 28 Jun 2014 22:20:44 -0400 Subject: [PATCH 09/59] scripting: no eval with negative key count Negative key count causes segfault in Lua functions. Fixes #1842 Closes #1843 --- src/scripting.c | 3 +++ tests/unit/scripting.tcl | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/src/scripting.c b/src/scripting.c index ef00eede..0a511e98 100644 --- a/src/scripting.c +++ b/src/scripting.c @@ -910,6 +910,9 @@ void evalGenericCommand(redisClient *c, int evalsha) { if (numkeys > (c->argc - 3)) { addReplyError(c,"Number of keys can't be greater than number of args"); return; + } else if (numkeys < 0) { + addReplyError(c,"Number of keys can't be negative"); + return; } /* We obtain the script SHA1, then check if this function is already diff --git a/tests/unit/scripting.tcl b/tests/unit/scripting.tcl index 4190a0a4..d0c6f5d7 100644 --- a/tests/unit/scripting.tcl +++ b/tests/unit/scripting.tcl @@ -358,6 +358,11 @@ start_server {tags {"scripting"}} { return redis.call("get", "key") } 0 } {12039611435714932082} + + test {Verify negative arg count is error instead of crash (issue #1842)} { + catch { r eval { return "hello" } -12 } e + set e + } {ERR Number of keys can't be negative} } # Start a new server since the last test in this stanza will kill the From 53fdfda9e3316a5763c78569fa74bf42e1c4b3a7 Mon Sep 17 00:00:00 2001 From: Jan-Erik Rediger Date: Sun, 29 Jun 2014 12:32:06 +0200 Subject: [PATCH 10/59] Handle large getrange requests Previously the end was casted to a smaller type which resulted in a wrong check and failed with values larger than handled by unsigned. Closes #1847, #1844 --- src/t_string.c | 2 +- tests/unit/basic.tcl | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/t_string.c b/src/t_string.c index 41e4b3b7..397363c5 100644 --- a/src/t_string.c +++ b/src/t_string.c @@ -255,7 +255,7 @@ void getrangeCommand(redisClient *c) { if (end < 0) end = strlen+end; if (start < 0) start = 0; if (end < 0) end = 0; - if ((unsigned)end >= strlen) end = strlen-1; + if ((size_t)end >= strlen) end = strlen-1; /* Precondition: end >= 0 && end < strlen, so the only condition where * nothing can be returned is: start > end. */ diff --git a/tests/unit/basic.tcl b/tests/unit/basic.tcl index 6f7fe292..2579cc9d 100644 --- a/tests/unit/basic.tcl +++ b/tests/unit/basic.tcl @@ -769,4 +769,9 @@ start_server {tags {"basic"}} { r keys * r keys * } {dlskeriewrioeuwqoirueioqwrueoqwrueqw} + + test {GETRANGE with huge ranges, Github issue #1844} { + r set foo bar + r getrange foo 0 4294967297 + } {bar} } From 87815ab5ba305770c0e6de7995b1688e55602589 Mon Sep 17 00:00:00 2001 From: Matt Stancliff Date: Mon, 21 Jul 2014 17:31:21 -0400 Subject: [PATCH 11/59] Fix key extraction for SORT We only want to use the last STORE key, but we have to record we actually found a STORE key so we can increment the final return key count. Test added to prevent further regression. Closes #1883, #1645, #1647 --- src/db.c | 5 +++-- tests/unit/sort.tcl | 8 ++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/db.c b/src/db.c index c83ab2ee..cd2cb1a2 100644 --- a/src/db.c +++ b/src/db.c @@ -1076,7 +1076,7 @@ int *evalGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) * follow in SQL-alike style. Here we parse just the minimum in order to * correctly identify keys in the "STORE" option. */ int *sortGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) { - int i, j, num, *keys; + int i, j, num, *keys, found_store = 0; REDIS_NOTUSED(cmd); num = 0; @@ -1107,12 +1107,13 @@ int *sortGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkeys) /* Note: we don't increment "num" here and continue the loop * to be sure to process the *last* "STORE" option if multiple * ones are provided. This is same behavior as SORT. */ + found_store = 1; keys[num] = i+1; /* */ break; } } } - *numkeys = num; + *numkeys = num + found_store; return keys; } diff --git a/tests/unit/sort.tcl b/tests/unit/sort.tcl index f48f88b5..54b0cc7e 100644 --- a/tests/unit/sort.tcl +++ b/tests/unit/sort.tcl @@ -95,6 +95,14 @@ start_server { assert_encoding ziplist sort-res } + test "SORT extracts STORE correctly" { + r command getkeys sort abc store def + } {abc def} + + test "SORT extracts multiple STORE correctly" { + r command getkeys sort abc store invalid store stillbad store def + } {abc def} + test "SORT DESC" { assert_equal [lsort -decreasing -integer $result] [r sort tosort DESC] } From c82e0b701f86989711988dae8be97bdbe63395ba Mon Sep 17 00:00:00 2001 From: Matt Stancliff Date: Fri, 1 Aug 2014 13:01:33 -0400 Subject: [PATCH 12/59] Fix intset midpoint selection The classic (min+max)/2 is provably unsafe. Fixed as recommended in research: http://googleresearch.blogspot.com/2006/06/extra-extra-read-all-about-it-nearly.html Fix inspired by @wjin, but I used a different approach. (later, I found @kuebler fixed the same issue too). Fixes #1741, #1602 --- src/intset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/intset.c b/src/intset.c index b61530e4..5d894e3c 100644 --- a/src/intset.c +++ b/src/intset.c @@ -133,7 +133,7 @@ static uint8_t intsetSearch(intset *is, int64_t value, uint32_t *pos) { } while(max >= min) { - mid = (min+max)/2; + mid = ((unsigned int)min + (unsigned int)max) >> 1; cur = _intsetGet(is,mid); if (value > cur) { min = mid+1; From d99a7246f805f20a99bd2fa428c10a64433e6e81 Mon Sep 17 00:00:00 2001 From: Matt Stancliff Date: Wed, 26 Mar 2014 22:15:44 -0400 Subject: [PATCH 13/59] Add graceful exit when Ctrl-C is received --- src/redis.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/redis.c b/src/redis.c index 5ddbc925..faed6733 100644 --- a/src/redis.c +++ b/src/redis.c @@ -3399,10 +3399,21 @@ void redisAsciiArt(void) { zfree(buf); } -static void sigtermHandler(int sig) { - REDIS_NOTUSED(sig); +static void sigShutdownHandler(int sig) { + char *msg; - redisLogFromHandler(REDIS_WARNING,"Received SIGTERM, scheduling shutdown..."); + switch (sig) { + case SIGINT: + msg = "Received SIGINT scheduling shutdown..."; + break; + case SIGTERM: + msg = "Received SIGTERM scheduling shutdown..."; + break; + default: + msg = "Received shutdown signal, scheduling shutdown..."; + }; + + redisLogFromHandler(REDIS_WARNING, msg); server.shutdown_asap = 1; } @@ -3413,8 +3424,9 @@ void setupSignalHandlers(void) { * Otherwise, sa_handler is used. */ sigemptyset(&act.sa_mask); act.sa_flags = 0; - act.sa_handler = sigtermHandler; + act.sa_handler = sigShutdownHandler; sigaction(SIGTERM, &act, NULL); + signal(SIGINT, sigShutdownHandler); #ifdef HAVE_BACKTRACE sigemptyset(&act.sa_mask); From 7bb25f8a46cafee90ba927d98141ccfa57e190df Mon Sep 17 00:00:00 2001 From: antirez Date: Thu, 7 Aug 2014 16:32:50 +0200 Subject: [PATCH 14/59] Force quit when receiving a second SIGINT. Also quit ASAP when we are still loading a DB, since care is not needed in this special condition, especially for a SIGINT. --- src/rdb.c | 2 +- src/redis.c | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/rdb.c b/src/rdb.c index ce5f99c9..2d6ac85f 100644 --- a/src/rdb.c +++ b/src/rdb.c @@ -766,7 +766,7 @@ int rdbSaveBackground(char *filename) { void rdbRemoveTempFile(pid_t childpid) { char tmpfile[256]; - snprintf(tmpfile,256,"temp-%d.rdb", (int) childpid); + snprintf(tmpfile,sizeof(tmpfile),"temp-%d.rdb", (int) childpid); unlink(tmpfile); } diff --git a/src/redis.c b/src/redis.c index faed6733..c5c3f79b 100644 --- a/src/redis.c +++ b/src/redis.c @@ -3413,6 +3413,18 @@ static void sigShutdownHandler(int sig) { msg = "Received shutdown signal, scheduling shutdown..."; }; + /* SIGINT is often delivered via Ctrl+C in an interactive session. + * If we receive the signal the second time, we interpret this as + * the user really wanting to quit ASAP without waiting to persist + * on disk. */ + if (server.shutdown_asap && sig == SIGINT) { + redisLogFromHandler(REDIS_WARNING, "You insist... exiting now."); + rdbRemoveTempFile(getpid()); + exit(1); /* Exit with an error since this was not a clean shutdown. */ + } else if (server.loading) { + exit(0); + } + redisLogFromHandler(REDIS_WARNING, msg); server.shutdown_asap = 1; } @@ -3426,7 +3438,7 @@ void setupSignalHandlers(void) { act.sa_flags = 0; act.sa_handler = sigShutdownHandler; sigaction(SIGTERM, &act, NULL); - signal(SIGINT, sigShutdownHandler); + sigaction(SIGINT, &act, NULL); #ifdef HAVE_BACKTRACE sigemptyset(&act.sa_mask); From c49378fe3e6f8900e753ff60a1b1f59e2e2c8755 Mon Sep 17 00:00:00 2001 From: Kashif Rasul Date: Fri, 4 Apr 2014 10:25:40 +0200 Subject: [PATCH 15/59] Fix issues raised by clang analyzer Modified by @antirez since the original fix to genInfoString() looked weak. Probably the clang analyzer complained about `section` being possibly NULL, and strcasecmp() called with a NULL pointer. In the practice this can never happen, still for the sake of correctness the right fix is not to modify only the first call, but to set `section` to the value of "default" if it happens to be NULL. Closes #1660 --- src/redis-cli.c | 1 + src/redis.c | 7 +++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/redis-cli.c b/src/redis-cli.c index 89afbbcb..eafeb190 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -644,6 +644,7 @@ static int cliSendCommand(int argc, char **argv, int repeat) { printf("Entering slave output mode... (press Ctrl-C to quit)\n"); slaveMode(); config.slave_mode = 0; + free(argvlen); return REDIS_ERR; /* Error = slaveMode lost connection to master */ } diff --git a/src/redis.c b/src/redis.c index c5c3f79b..dff480c0 100644 --- a/src/redis.c +++ b/src/redis.c @@ -2562,10 +2562,9 @@ sds genRedisInfoString(char *section) { int allsections = 0, defsections = 0; int sections = 0; - if (section) { - allsections = strcasecmp(section,"all") == 0; - defsections = strcasecmp(section,"default") == 0; - } + if (section == NULL) section = "default"; + allsections = strcasecmp(section,"all") == 0; + defsections = strcasecmp(section,"default") == 0; getrusage(RUSAGE_SELF, &self_ru); getrusage(RUSAGE_CHILDREN, &c_ru); From 9b4efe6cf4e165bac8031a26541ab04ff6d31402 Mon Sep 17 00:00:00 2001 From: ripcurld00d Date: Sun, 13 Apr 2014 21:09:54 +0300 Subject: [PATCH 16/59] redis-check-dump: use names instead of magic nums Use constants to avoid magic numbers in `types`, which is an array that stores the names of `REDIS` types. Closes #1681 --- src/redis-check-dump.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/redis-check-dump.c b/src/redis-check-dump.c index a4f103fd..185cd243 100644 --- a/src/redis-check-dump.c +++ b/src/redis-check-dump.c @@ -138,8 +138,10 @@ typedef struct { * at runtime to avoid strange compiler optimizations. */ static double R_Zero, R_PosInf, R_NegInf, R_Nan; +#define MAX_TYPES_NUM 256 +#define MAX_TYPE_NAME_LEN 16 /* store string types for output */ -static char types[256][16]; +static char types[MAX_TYPES_NUM][MAX_TYPE_NAME_LEN]; /* Return true if 't' is a valid object type. */ int checkType(unsigned char t) { From 67c4fbed8206cc091ff6a699c38cfa19e52eb005 Mon Sep 17 00:00:00 2001 From: Edgars Irmejs Date: Mon, 21 Apr 2014 21:48:14 +0300 Subject: [PATCH 17/59] Change unixsocketperm comment to 700 from 755 According to unix manuals, "Connecting to the socket object requires read/write permission." -- mode 755 is useless for anybody other than the owner. Fixes #1696 --- redis.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redis.conf b/redis.conf index 33f28a5b..ae774d6f 100644 --- a/redis.conf +++ b/redis.conf @@ -68,7 +68,7 @@ tcp-backlog 511 # on a unix socket when not specified. # # unixsocket /tmp/redis.sock -# unixsocketperm 755 +# unixsocketperm 700 # Close the connection after a client is idle for N seconds (0 to disable) timeout 0 From 6df1251baa68d44ef27d6abff512c7286278502c Mon Sep 17 00:00:00 2001 From: Jan-Erik Rediger Date: Wed, 7 May 2014 18:25:10 +0200 Subject: [PATCH 18/59] install_server.sh: add missing bang This was discovered by _bodya and reported in the IRC channel. Everything worked fine as these scripts are always executed as shell scripts. Closes #1728 --- utils/install_server.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/install_server.sh b/utils/install_server.sh index 15b60a08..98e047e3 100755 --- a/utils/install_server.sh +++ b/utils/install_server.sh @@ -152,7 +152,7 @@ rm -f $TMP_FILE #we hard code the configs here to avoid issues with templates containing env vars #kinda lame but works! REDIS_INIT_HEADER=\ -"#/bin/sh\n +"#!/bin/sh\n #Configurations injected by install_server below....\n\n EXEC=$REDIS_EXECUTABLE\n CLIEXEC=$CLI_EXEC\n @@ -193,7 +193,7 @@ fi # warning if init info is not available. cat > ${TMP_FILE} < Date: Fri, 1 Aug 2014 13:07:38 -0400 Subject: [PATCH 19/59] Fix assert technical correctness dictAdd returns DICT_OK, not REDIS_OK. They both have the same underlying values, so it works even though the code is technically wrong. Fixes #1512 --- src/rdb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rdb.c b/src/rdb.c index 2d6ac85f..89e77e6f 100644 --- a/src/rdb.c +++ b/src/rdb.c @@ -943,7 +943,7 @@ robj *rdbLoadObject(int rdbtype, rio *rdb) { /* Add pair to hash table */ ret = dictAdd((dict*)o->ptr, field, value); - redisAssert(ret == REDIS_OK); + redisAssert(ret == DICT_OK); } /* All pairs should be read by now */ From 23f08510d5c63a1936bced5a3aaf7ae4860090f9 Mon Sep 17 00:00:00 2001 From: cubicdaiya Date: Sun, 16 Mar 2014 08:51:54 +0900 Subject: [PATCH 20/59] Use 'void' for zero-argument functions According to the C standard, it is desirable to give the type 'void' to functions have no argument. Closes #1631 --- src/config.c | 2 +- src/rand.c | 4 ++-- src/redis-check-dump.c | 4 ++-- src/redis-cli.c | 18 +++++++++--------- src/redis.c | 8 ++++---- src/redis.h | 4 ++-- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/config.c b/src/config.c index b0fc50b9..04246fcb 100644 --- a/src/config.c +++ b/src/config.c @@ -73,7 +73,7 @@ void appendServerSaveParams(time_t seconds, int changes) { server.saveparamslen++; } -void resetServerSaveParams() { +void resetServerSaveParams(void) { zfree(server.saveparams); server.saveparams = NULL; server.saveparamslen = 0; diff --git a/src/rand.c b/src/rand.c index 36cb417c..09b0508f 100644 --- a/src/rand.c +++ b/src/rand.c @@ -66,7 +66,7 @@ #define HI_BIT (1L << (2 * N - 1)) static uint32_t x[3] = { X0, X1, X2 }, a[3] = { A0, A1, A2 }, c = C; -static void next(); +static void next(void); int32_t redisLrand48() { next(); @@ -77,7 +77,7 @@ void redisSrand48(int32_t seedval) { SEED(X0, LOW(seedval), HIGH(seedval)); } -static void next() { +static void next(void) { uint32_t p[2], q[2], r[2], carry0, carry1; MUL(a[0], x[0], p); diff --git a/src/redis-check-dump.c b/src/redis-check-dump.c index 185cd243..854e4325 100644 --- a/src/redis-check-dump.c +++ b/src/redis-check-dump.c @@ -168,7 +168,7 @@ int readBytes(void *target, long num) { return 1; } -int processHeader() { +int processHeader(void) { char buf[10] = "_________"; int dump_version; @@ -602,7 +602,7 @@ void printErrorStack(entry *e) { } } -void process() { +void process(void) { uint64_t num_errors = 0, num_valid_ops = 0, num_valid_bytes = 0; entry entry; int dump_version = processHeader(); diff --git a/src/redis-cli.c b/src/redis-cli.c index eafeb190..d892e80c 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -98,7 +98,7 @@ static struct config { } config; static volatile sig_atomic_t force_cancel_loop = 0; -static void usage(); +static void usage(void); static void slaveMode(void); char *redisGitSHA1(void); char *redisGitDirty(void); @@ -158,7 +158,7 @@ typedef struct { static helpEntry *helpEntries; static int helpEntriesLen; -static sds cliVersion() { +static sds cliVersion(void) { sds version; version = sdscatprintf(sdsempty(), "%s", REDIS_VERSION); @@ -172,7 +172,7 @@ static sds cliVersion() { return version; } -static void cliInitHelp() { +static void cliInitHelp(void) { int commandslen = sizeof(commandHelp)/sizeof(struct commandHelp); int groupslen = sizeof(commandGroups)/sizeof(char*); int i, len, pos = 0; @@ -211,7 +211,7 @@ static void cliOutputCommandHelp(struct commandHelp *help, int group) { } /* Print generic help. */ -static void cliOutputGenericHelp() { +static void cliOutputGenericHelp(void) { sds version = cliVersion(); printf( "redis-cli %s\r\n" @@ -368,7 +368,7 @@ static int cliConnect(int force) { return REDIS_OK; } -static void cliPrintContextError() { +static void cliPrintContextError(void) { if (context == NULL) return; fprintf(stderr,"Error: %s\n",context->errstr); } @@ -805,7 +805,7 @@ static sds readArgFromStdin(void) { return arg; } -static void usage() { +static void usage(void) { sds version = cliVersion(); fprintf(stderr, "redis-cli %s\n" @@ -874,7 +874,7 @@ static char **convertToSds(int count, char** args) { } #define LINE_BUFLEN 4096 -static void repl() { +static void repl(void) { sds historyfile = NULL; int history = 0; char *line; @@ -1677,7 +1677,7 @@ void bytesToHuman(char *s, long long n) { } } -static void statMode() { +static void statMode(void) { redisReply *reply; long aux, requests = 0; int i = 0; @@ -1763,7 +1763,7 @@ static void statMode() { * Scan mode *--------------------------------------------------------------------------- */ -static void scanMode() { +static void scanMode(void) { redisReply *reply; unsigned long long cur = 0; diff --git a/src/redis.c b/src/redis.c index dff480c0..ff4cbb17 100644 --- a/src/redis.c +++ b/src/redis.c @@ -1376,7 +1376,7 @@ void createSharedObjects(void) { shared.maxstring = createStringObject("maxstring",9); } -void initServerConfig() { +void initServerConfig(void) { int j; getRandomHexChars(server.runid,REDIS_RUN_ID_SIZE); @@ -1696,7 +1696,7 @@ void resetServerStats(void) { server.ops_sec_last_sample_ops = 0; } -void initServer() { +void initServer(void) { int j; signal(SIGHUP, SIG_IGN); @@ -3349,7 +3349,7 @@ void daemonize(void) { } } -void version() { +void version(void) { printf("Redis server v=%s sha=%s:%d malloc=%s bits=%d build=%llx\n", REDIS_VERSION, redisGitSHA1(), @@ -3360,7 +3360,7 @@ void version() { exit(0); } -void usage() { +void usage(void) { fprintf(stderr,"Usage: ./redis-server [/path/to/redis.conf] [options]\n"); fprintf(stderr," ./redis-server - (read config from stdin)\n"); fprintf(stderr," ./redis-server -v or --version\n"); diff --git a/src/redis.h b/src/redis.h index 2cf96028..4d180da2 100644 --- a/src/redis.h +++ b/src/redis.h @@ -1216,7 +1216,7 @@ void redisLog(int level, const char *fmt, ...); #endif void redisLogRaw(int level, const char *msg); void redisLogFromHandler(int level, const char *msg); -void usage(); +void usage(void); void updateDictResizePolicy(void); int htNeedsResize(dict *dict); void oom(const char *msg); @@ -1276,7 +1276,7 @@ sds keyspaceEventsFlagsToString(int flags); /* Configuration */ void loadServerConfig(char *filename, char *options); void appendServerSaveParams(time_t seconds, int changes); -void resetServerSaveParams(); +void resetServerSaveParams(void); struct rewriteConfigState; /* Forward declaration to export API. */ void rewriteConfigRewriteLine(struct rewriteConfigState *state, char *option, sds line, int force); int rewriteConfig(char *path); From 7a2450a7e5852beb29a923caf091161e06e39cc9 Mon Sep 17 00:00:00 2001 From: Joshua Anderson Date: Sun, 16 Mar 2014 20:22:36 -0700 Subject: [PATCH 21/59] src/Makefile: Reword "to run make test" message Closes #1610 --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 901104b2..ca7a0be8 100644 --- a/src/Makefile +++ b/src/Makefile @@ -125,7 +125,7 @@ REDIS_CHECK_AOF_OBJ=redis-check-aof.o all: $(REDIS_SERVER_NAME) $(REDIS_SENTINEL_NAME) $(REDIS_CLI_NAME) $(REDIS_BENCHMARK_NAME) $(REDIS_CHECK_DUMP_NAME) $(REDIS_CHECK_AOF_NAME) @echo "" - @echo "Hint: To run 'make test' is a good idea ;)" + @echo "Hint: It's a good idea to run 'make test' ;)" @echo "" .PHONY: all From f510cfb4ef724987a145ffbbba00230e976787bf Mon Sep 17 00:00:00 2001 From: Xian Li Date: Tue, 18 Mar 2014 11:37:08 +0800 Subject: [PATCH 22/59] memtest: Add missing free() Closes #1614 --- src/memtest.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/memtest.c b/src/memtest.c index cabfb5c8..18d821b1 100644 --- a/src/memtest.c +++ b/src/memtest.c @@ -237,6 +237,7 @@ void memtest_test(size_t megabytes, int passes) { memtest_progress_end(); memtest_compare_times(m,bytes,pass,4); } + free(m); } void memtest_non_destructive_invert(void *addr, size_t size) { From a8d3e930bced31cc0f5211cc0874ca6f837faca0 Mon Sep 17 00:00:00 2001 From: Jim Howard Date: Fri, 6 Dec 2013 22:27:00 -0500 Subject: [PATCH 23/59] Remove redundant event loop fd processing Reason: https://github.com/antirez/redis/pull/1450#issuecomment-30432925 Closes #1450 --- src/ae.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ae.c b/src/ae.c index 164f8fde..63a1ab4e 100644 --- a/src/ae.c +++ b/src/ae.c @@ -156,8 +156,9 @@ void aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask) { if (fd >= eventLoop->setsize) return; aeFileEvent *fe = &eventLoop->events[fd]; - if (fe->mask == AE_NONE) return; + + aeApiDelEvent(eventLoop, fd, mask); fe->mask = fe->mask & (~mask); if (fd == eventLoop->maxfd && fe->mask == AE_NONE) { /* Update the max fd */ @@ -167,7 +168,6 @@ void aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask) if (eventLoop->events[j].mask != AE_NONE) break; eventLoop->maxfd = j; } - aeApiDelEvent(eventLoop, fd, mask); } int aeGetFileEvents(aeEventLoop *eventLoop, int fd) { From 7e9f24d6940f0edba71f15f8606e58045a84ead0 Mon Sep 17 00:00:00 2001 From: Samuel Chou Date: Mon, 9 Dec 2013 10:18:36 -0800 Subject: [PATCH 24/59] Improve accuracy of HAVE_ATOMIC dependency check [I had to split out the clang check due to clang *really* not liking the __GLIBC_PREREQ macro; -matt] Closes #1456 --- src/config.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/config.h b/src/config.h index 1bc70a13..57d07599 100644 --- a/src/config.h +++ b/src/config.h @@ -187,9 +187,14 @@ void setproctitle(const char *fmt, ...); #if (__i386 || __amd64 || __powerpc__) && __GNUC__ #define GNUC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) -#if (GNUC_VERSION >= 40100) || defined(__clang__) +#if defined(__clang__) #define HAVE_ATOMIC #endif +#if (defined(__GLIBC__) && defined(__GLIBC_PREREQ)) +#if (GNUC_VERSION >= 40100 && __GLIBC_PREREQ(2, 6)) +#define HAVE_ATOMIC +#endif +#endif #endif #endif From 4bb6844e4354738b1fc7400be016277e22fa585b Mon Sep 17 00:00:00 2001 From: Xiaojie Zhang Date: Wed, 22 Jan 2014 21:23:54 +0800 Subject: [PATCH 25/59] Avoid unnecessary decoding in ziplist.c Closes #1519 --- src/ziplist.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/ziplist.c b/src/ziplist.c index d78f8f5d..4a011110 100644 --- a/src/ziplist.c +++ b/src/ziplist.c @@ -576,19 +576,19 @@ static unsigned char *__ziplistDelete(unsigned char *zl, unsigned char *p, unsig /* Insert item at "p". */ static unsigned char *__ziplistInsert(unsigned char *zl, unsigned char *p, unsigned char *s, unsigned int slen) { - size_t curlen = intrev32ifbe(ZIPLIST_BYTES(zl)), reqlen, prevlen = 0; + size_t curlen = intrev32ifbe(ZIPLIST_BYTES(zl)), reqlen; + unsigned int prevlensize, prevlen = 0; size_t offset; int nextdiff = 0; unsigned char encoding = 0; long long value = 123456789; /* initialized to avoid warning. Using a value that is easy to see if for some reason we use it uninitialized. */ - zlentry entry, tail; + zlentry tail; /* Find out prevlen for the entry that is inserted. */ if (p[0] != ZIP_END) { - entry = zipEntry(p); - prevlen = entry.prevrawlen; + ZIP_DECODE_PREVLEN(p, prevlensize, prevlen); } else { unsigned char *ptail = ZIPLIST_ENTRY_TAIL(zl); if (ptail[0] != ZIP_END) { @@ -676,15 +676,15 @@ unsigned char *ziplistPush(unsigned char *zl, unsigned char *s, unsigned int sle * doesn't contain an element at the provided index, NULL is returned. */ unsigned char *ziplistIndex(unsigned char *zl, int index) { unsigned char *p; - zlentry entry; + unsigned int prevlensize, prevlen = 0; if (index < 0) { index = (-index)-1; p = ZIPLIST_ENTRY_TAIL(zl); if (p[0] != ZIP_END) { - entry = zipEntry(p); - while (entry.prevrawlen > 0 && index--) { - p -= entry.prevrawlen; - entry = zipEntry(p); + ZIP_DECODE_PREVLEN(p, prevlensize, prevlen); + while (prevlen > 0 && index--) { + p -= prevlen; + ZIP_DECODE_PREVLEN(p, prevlensize, prevlen); } } } else { @@ -722,7 +722,7 @@ unsigned char *ziplistNext(unsigned char *zl, unsigned char *p) { /* Return pointer to previous entry in ziplist. */ unsigned char *ziplistPrev(unsigned char *zl, unsigned char *p) { - zlentry entry; + unsigned int prevlensize, prevlen = 0; /* Iterating backwards from ZIP_END should return the tail. When "p" is * equal to the first element of the list, we're already at the head, @@ -733,9 +733,9 @@ unsigned char *ziplistPrev(unsigned char *zl, unsigned char *p) { } else if (p == ZIPLIST_ENTRY_HEAD(zl)) { return NULL; } else { - entry = zipEntry(p); - assert(entry.prevrawlen > 0); - return p-entry.prevrawlen; + ZIP_DECODE_PREVLEN(p, prevlensize, prevlen); + assert(prevlen > 0); + return p-prevlen; } } From 25791550e085930c196b9234465f6538fe8ee383 Mon Sep 17 00:00:00 2001 From: Matt Stancliff Date: Fri, 1 Aug 2014 13:57:30 -0400 Subject: [PATCH 26/59] pubsub: Return integers for NUMSUB, not strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also adds test for numsub — due to tcl being tcl, it doesn't capture the "numberness" of the fix, but now we at least have one test case for numsub. Closes #1561 --- src/pubsub.c | 2 +- tests/unit/pubsub.tcl | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/pubsub.c b/src/pubsub.c index 720cd518..d6cfbdf3 100644 --- a/src/pubsub.c +++ b/src/pubsub.c @@ -358,7 +358,7 @@ void pubsubCommand(redisClient *c) { list *l = dictFetchValue(server.pubsub_channels,c->argv[j]); addReplyBulk(c,c->argv[j]); - addReplyBulkLongLong(c,l ? listLength(l) : 0); + addReplyLongLong(c,l ? listLength(l) : 0); } } else if (!strcasecmp(c->argv[1]->ptr,"numpat") && c->argc == 2) { /* PUBSUB NUMPAT */ diff --git a/tests/unit/pubsub.tcl b/tests/unit/pubsub.tcl index 18033bdf..9c7a43bf 100644 --- a/tests/unit/pubsub.tcl +++ b/tests/unit/pubsub.tcl @@ -196,6 +196,10 @@ start_server {tags {"pubsub"}} { $rd1 close } + test "NUMSUB returns numbers, not strings (#1561)" { + r pubsub numsub abc def + } {abc 0 def 0} + test "Mix SUBSCRIBE and PSUBSCRIBE" { set rd1 [redis_deferring_client] assert_equal {1} [subscribe $rd1 {foo.bar}] From 498ad7482b2eb4ebc6f4c7458fe6a35f244adaf6 Mon Sep 17 00:00:00 2001 From: Matt Stancliff Date: Fri, 1 Aug 2014 14:55:24 -0400 Subject: [PATCH 27/59] Reject MOVE to non-integer DBs Previously, "MOVE key somestring" would move the key to DB 0 which is just unexpected and wrong. String as DB == error. Test added too. Modified by @antirez in order to use the getLongLongFromObject() API instead of strtol(). Fixes #1428 --- src/db.c | 7 ++++++- tests/unit/basic.tcl | 6 ++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/db.c b/src/db.c index cd2cb1a2..e665008e 100644 --- a/src/db.c +++ b/src/db.c @@ -707,6 +707,7 @@ void moveCommand(redisClient *c) { robj *o; redisDb *src, *dst; int srcid; + long long dbid; if (server.cluster_enabled) { addReplyError(c,"MOVE is not allowed in cluster mode"); @@ -716,7 +717,11 @@ void moveCommand(redisClient *c) { /* Obtain source and target DB pointers */ src = c->db; srcid = c->db->id; - if (selectDb(c,atoi(c->argv[2]->ptr)) == REDIS_ERR) { + + if (getLongLongFromObject(c->argv[2],&dbid) == REDIS_ERR || + dbid < INT_MIN || dbid > INT_MAX || + selectDb(c,dbid) == REDIS_ERR) + { addReply(c,shared.outofrangeerr); return; } diff --git a/tests/unit/basic.tcl b/tests/unit/basic.tcl index 2579cc9d..11037608 100644 --- a/tests/unit/basic.tcl +++ b/tests/unit/basic.tcl @@ -404,6 +404,12 @@ start_server {tags {"basic"}} { r move mykey 10 } {0} + test {MOVE against non-integer DB (#1428)} { + r set mykey hello + catch {r move mykey notanumber} e + set e + } {*ERR*index out of range} + test {SET/GET keys in different DBs} { r set a hello r set b world From 354119e4c50fbb3074f2d085300a1b399d4d89af Mon Sep 17 00:00:00 2001 From: charsyam Date: Sat, 25 May 2013 19:22:24 +0900 Subject: [PATCH 28/59] Remove unused LINE_BUFLEN definition Closes #1129 --- src/redis-cli.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/redis-cli.c b/src/redis-cli.c index d892e80c..43a35560 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -873,7 +873,6 @@ static char **convertToSds(int count, char** args) { return sds; } -#define LINE_BUFLEN 4096 static void repl(void) { sds historyfile = NULL; int history = 0; From af62d9a687c7f61178c1fd8a4c7c9f1cc3d5083f Mon Sep 17 00:00:00 2001 From: Chris Lamb Date: Thu, 11 Jul 2013 12:45:15 +0100 Subject: [PATCH 29/59] redis-check-dump: Prevent segfault if can't malloc Found by The Mayhem Team (Alexandre Rebert, Thanassis Avgerinos, Sang Kil Cha, David Brumley, Manuel Egele) Cylab, Carnegie Mellon University. See http://bugs.debian.org/716259 for more. Signed-off-by: Chris Lamb Fixes #1191 --- src/redis-check-dump.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/redis-check-dump.c b/src/redis-check-dump.c index 854e4325..c8b0f696 100644 --- a/src/redis-check-dump.c +++ b/src/redis-check-dump.c @@ -337,6 +337,7 @@ char* loadStringObject() { if (len == REDIS_RDB_LENERR) return NULL; char *buf = malloc(sizeof(char) * (len+1)); + if (buf == NULL) return NULL; buf[len] = '\0'; if (!readBytes(buf, len)) { free(buf); From dec58464d8d41f9438fcfaac07b71a8e4b7ac310 Mon Sep 17 00:00:00 2001 From: SungBin_Hong Date: Tue, 15 Oct 2013 00:12:06 +0900 Subject: [PATCH 30/59] Free memory in clusterLoadConfig error handler Closes #1327 --- src/cluster.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cluster.c b/src/cluster.c index 0d908349..cb9efc64 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -284,6 +284,7 @@ int clusterLoadConfig(char *filename) { fmterr: redisLog(REDIS_WARNING, "Unrecoverable error: corrupted cluster config file."); + zfree(line); fclose(fp); exit(1); } From da0132638f15d81782c5543ed49a1d1f17594d9d Mon Sep 17 00:00:00 2001 From: Matt Stancliff Date: Fri, 1 Aug 2014 15:42:50 -0400 Subject: [PATCH 31/59] Cleanup double semicolons Closes #1161 --- src/multi.c | 2 +- src/redis-check-dump.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/multi.c b/src/multi.c index 3d78e148..c8287645 100644 --- a/src/multi.c +++ b/src/multi.c @@ -72,7 +72,7 @@ void queueMultiCommand(redisClient *c) { void discardTransaction(redisClient *c) { freeClientMultiState(c); initClientMultiState(c); - c->flags &= ~(REDIS_MULTI|REDIS_DIRTY_CAS|REDIS_DIRTY_EXEC);; + c->flags &= ~(REDIS_MULTI|REDIS_DIRTY_CAS|REDIS_DIRTY_EXEC); unwatchAllKeys(c); } diff --git a/src/redis-check-dump.c b/src/redis-check-dump.c index c8b0f696..54646200 100644 --- a/src/redis-check-dump.c +++ b/src/redis-check-dump.c @@ -614,7 +614,7 @@ void process(void) { printf("RDB version >= 5 but no room for checksum.\n"); exit(1); } - positions[0].size -= 8;; + positions[0].size -= 8; } level = 1; From de5465baf7f30b1040ae7e8c36ad8fec14edfea4 Mon Sep 17 00:00:00 2001 From: charsyam Date: Sun, 17 Feb 2013 20:10:48 -0800 Subject: [PATCH 32/59] Refactor cluster flag printing Less copy/paste code duplication. Closes #952 --- src/cluster.c | 56 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/src/cluster.c b/src/cluster.c index cb9efc64..cd1100ae 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -73,6 +73,39 @@ void clusterCloseAllSlots(void); void clusterSetNodeAsMaster(clusterNode *n); void clusterDelNode(clusterNode *delnode); +struct redisNodeFlags { + uint16_t flag; + char *attr; +}; + +static struct redisNodeFlags nodeflags[] = { + {REDIS_NODE_MYSELF, "myself,"}, + {REDIS_NODE_MASTER, "master,"}, + {REDIS_NODE_SLAVE, "slave,"}, + {REDIS_NODE_PFAIL, "fail?,"}, + {REDIS_NODE_FAIL, "fail,"}, + {REDIS_NODE_HANDSHAKE, "handshake,"}, + {REDIS_NODE_NOADDR, "noaddr,"} +}; + +sds representRedisNodeFlags(sds ci, uint16_t flags) { + if (flags == 0) { + ci = sdscat(ci,"noflags"); + } else { + int size = sizeof(nodeflags) / sizeof(struct redisNodeFlags); + for (int i=0; i < size; i++) { + struct redisNodeFlags *nodeflag = nodeflags + i; + if (flags & nodeflag->flag) { + ci = sdscat(ci, nodeflag->attr); + } + } + + if (ci[sdslen(ci)-1] == ',') ci[sdslen(ci)-1] = ' '; + } + + return ci; +} + /* ----------------------------------------------------------------------------- * Initialization * -------------------------------------------------------------------------- */ @@ -1145,20 +1178,11 @@ void clusterProcessGossipSection(clusterMsg *hdr, clusterLink *link) { clusterNode *sender = link->node ? link->node : clusterLookupNode(hdr->sender); while(count--) { - sds ci = sdsempty(); uint16_t flags = ntohs(g->flags); clusterNode *node; - if (flags == 0) ci = sdscat(ci,"noflags,"); - if (flags & REDIS_NODE_MYSELF) ci = sdscat(ci,"myself,"); - if (flags & REDIS_NODE_MASTER) ci = sdscat(ci,"master,"); - if (flags & REDIS_NODE_SLAVE) ci = sdscat(ci,"slave,"); - if (flags & REDIS_NODE_PFAIL) ci = sdscat(ci,"fail?,"); - if (flags & REDIS_NODE_FAIL) ci = sdscat(ci,"fail,"); - if (flags & REDIS_NODE_HANDSHAKE) ci = sdscat(ci,"handshake,"); - if (flags & REDIS_NODE_NOADDR) ci = sdscat(ci,"noaddr,"); - if (ci[sdslen(ci)-1] == ',') ci[sdslen(ci)-1] = ' '; - + sds ci = sdsempty(); + ci = representRedisNodeFlags(ci, flags); redisLog(REDIS_DEBUG,"GOSSIP %.40s %s:%d %s", g->nodename, g->ip, @@ -3355,15 +3379,7 @@ sds clusterGenNodeDescription(clusterNode *node) { node->port); /* Flags */ - if (node->flags == 0) ci = sdscat(ci,"noflags,"); - if (node->flags & REDIS_NODE_MYSELF) ci = sdscat(ci,"myself,"); - if (node->flags & REDIS_NODE_MASTER) ci = sdscat(ci,"master,"); - if (node->flags & REDIS_NODE_SLAVE) ci = sdscat(ci,"slave,"); - if (node->flags & REDIS_NODE_PFAIL) ci = sdscat(ci,"fail?,"); - if (node->flags & REDIS_NODE_FAIL) ci = sdscat(ci,"fail,"); - if (node->flags & REDIS_NODE_HANDSHAKE) ci =sdscat(ci,"handshake,"); - if (node->flags & REDIS_NODE_NOADDR) ci = sdscat(ci,"noaddr,"); - if (ci[sdslen(ci)-1] == ',') ci[sdslen(ci)-1] = ' '; + ci = representRedisNodeFlags(ci, node->flags); /* Slave of... or just "-" */ if (node->slaveof) From ded57795ff860d27d2889641d0fea9554df4a973 Mon Sep 17 00:00:00 2001 From: antirez Date: Fri, 8 Aug 2014 15:52:04 +0200 Subject: [PATCH 33/59] representRedisNodeFlags() moved into right code section. The funciton was also modified in order to be more standalone and produce an output without trailing spaces, making the reuse simpler. The global variable was renamed in cammel case as most other Redis globals, except the main ones we refer too many times, like 'server'. --- src/cluster.c | 79 ++++++++++++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 38 deletions(-) diff --git a/src/cluster.c b/src/cluster.c index cd1100ae..81f82f93 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -72,39 +72,7 @@ void resetManualFailover(void); void clusterCloseAllSlots(void); void clusterSetNodeAsMaster(clusterNode *n); void clusterDelNode(clusterNode *delnode); - -struct redisNodeFlags { - uint16_t flag; - char *attr; -}; - -static struct redisNodeFlags nodeflags[] = { - {REDIS_NODE_MYSELF, "myself,"}, - {REDIS_NODE_MASTER, "master,"}, - {REDIS_NODE_SLAVE, "slave,"}, - {REDIS_NODE_PFAIL, "fail?,"}, - {REDIS_NODE_FAIL, "fail,"}, - {REDIS_NODE_HANDSHAKE, "handshake,"}, - {REDIS_NODE_NOADDR, "noaddr,"} -}; - -sds representRedisNodeFlags(sds ci, uint16_t flags) { - if (flags == 0) { - ci = sdscat(ci,"noflags"); - } else { - int size = sizeof(nodeflags) / sizeof(struct redisNodeFlags); - for (int i=0; i < size; i++) { - struct redisNodeFlags *nodeflag = nodeflags + i; - if (flags & nodeflag->flag) { - ci = sdscat(ci, nodeflag->attr); - } - } - - if (ci[sdslen(ci)-1] == ',') ci[sdslen(ci)-1] = ' '; - } - - return ci; -} +sds representRedisNodeFlags(sds ci, uint16_t flags); /* ----------------------------------------------------------------------------- * Initialization @@ -1180,9 +1148,9 @@ void clusterProcessGossipSection(clusterMsg *hdr, clusterLink *link) { while(count--) { uint16_t flags = ntohs(g->flags); clusterNode *node; + sds ci; - sds ci = sdsempty(); - ci = representRedisNodeFlags(ci, flags); + ci = representRedisNodeFlags(sdsempty(), flags); redisLog(REDIS_DEBUG,"GOSSIP %.40s %s:%d %s", g->nodename, g->ip, @@ -3361,9 +3329,40 @@ void clusterSetMaster(clusterNode *n) { } /* ----------------------------------------------------------------------------- - * CLUSTER command + * Nodes to string representation functions. * -------------------------------------------------------------------------- */ +struct redisNodeFlags { + uint16_t flag; + char *name; +}; + +static struct redisNodeFlags redisNodeFlagsTable[] = { + {REDIS_NODE_MYSELF, "myself,"}, + {REDIS_NODE_MASTER, "master,"}, + {REDIS_NODE_SLAVE, "slave,"}, + {REDIS_NODE_PFAIL, "fail?,"}, + {REDIS_NODE_FAIL, "fail,"}, + {REDIS_NODE_HANDSHAKE, "handshake,"}, + {REDIS_NODE_NOADDR, "noaddr,"} +}; + +/* Concatenate the comma separated list of node flags to the given SDS + * string 'ci'. */ +sds representRedisNodeFlags(sds ci, uint16_t flags) { + if (flags == 0) { + ci = sdscat(ci,"noflags,"); + } else { + int i, size = sizeof(redisNodeFlagsTable)/sizeof(struct redisNodeFlags); + for (i = 0; i < size; i++) { + struct redisNodeFlags *nodeflag = redisNodeFlagsTable + i; + if (flags & nodeflag->flag) ci = sdscat(ci, nodeflag->name); + } + } + sdsIncrLen(ci,-1); /* Remove trailing comma. */ + return ci; +} + /* Generate a csv-alike representation of the specified cluster node. * See clusterGenNodesDescription() top comment for more information. * @@ -3383,9 +3382,9 @@ sds clusterGenNodeDescription(clusterNode *node) { /* Slave of... or just "-" */ if (node->slaveof) - ci = sdscatprintf(ci,"%.40s ",node->slaveof->name); + ci = sdscatprintf(ci," %.40s ",node->slaveof->name); else - ci = sdscatprintf(ci,"- "); + ci = sdscatlen(ci," - ",3); /* Latency from the POV of this node, link status */ ci = sdscatprintf(ci,"%lld %lld %llu %s", @@ -3463,6 +3462,10 @@ sds clusterGenNodesDescription(int filter) { return ci; } +/* ----------------------------------------------------------------------------- + * CLUSTER command + * -------------------------------------------------------------------------- */ + int getSlotOrReply(redisClient *c, robj *o) { long long slot; From b57a4d07a210fd0c99d5a3cd286ffdcf9d639ad9 Mon Sep 17 00:00:00 2001 From: Daniel Price Date: Mon, 11 Mar 2013 18:04:40 -0700 Subject: [PATCH 34/59] Define AR to help with lua cross-compilation Closes #997 --- deps/Makefile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/deps/Makefile b/deps/Makefile index 5a95545d..e183ede9 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -60,10 +60,15 @@ endif LUA_CFLAGS+= -O2 -Wall -DLUA_ANSI $(CFLAGS) LUA_LDFLAGS+= $(LDFLAGS) +# lua's Makefile defines AR="ar rcu", which is unusual, and makes it more +# challenging to cross-compile lua (and redis). These defines make it easier +# to fit redis into cross-compilation environments, which typically set AR. +AR=ar +ARFLAGS=rcu lua: .make-prerequisites @printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR) - cd lua/src && $(MAKE) all CFLAGS="$(LUA_CFLAGS)" MYLDFLAGS="$(LUA_LDFLAGS)" + cd lua/src && $(MAKE) all CFLAGS="$(LUA_CFLAGS)" MYLDFLAGS="$(LUA_LDFLAGS)" AR="$(AR) $(ARFLAGS)" .PHONY: lua From 951eefae3c7a318860fd78ac60ec0b4c77aab10f Mon Sep 17 00:00:00 2001 From: NanXiao Date: Tue, 7 May 2013 14:59:03 +0800 Subject: [PATCH 35/59] Use resolv library in Solaris For some Solaris flavours, the inet_aton in in resolv library. Not linking this library will introduce link error. Improves compatability with older Solaris and still works on new Solaris. Closes #1092 --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index ca7a0be8..b2d25228 100644 --- a/src/Makefile +++ b/src/Makefile @@ -58,7 +58,7 @@ ifeq ($(uname_S),SunOS) # SunOS INSTALL=cp -pf FINAL_CFLAGS+= -D__EXTENSIONS__ -D_XPG6 - FINAL_LIBS+= -ldl -lnsl -lsocket -lpthread + FINAL_LIBS+= -ldl -lnsl -lsocket -lresolv -lpthread else ifeq ($(uname_S),Darwin) # Darwin (nothing to do) From 3426866e0a62926e62143b9ede8880e48e51a038 Mon Sep 17 00:00:00 2001 From: charsyam Date: Wed, 15 May 2013 00:15:25 +0900 Subject: [PATCH 36/59] Remove duplicate prototypes in redis.h Also moves acceptHandler() to be near the other accept...() functions. Closes #1105 --- src/redis.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/redis.h b/src/redis.h index 4d180da2..75c353fc 100644 --- a/src/redis.h +++ b/src/redis.h @@ -999,11 +999,10 @@ void freeClient(redisClient *c); void freeClientAsync(redisClient *c); void resetClient(redisClient *c); void sendReplyToClient(aeEventLoop *el, int fd, void *privdata, int mask); -void addReply(redisClient *c, robj *obj); void *addDeferredMultiBulkLength(redisClient *c); void setDeferredMultiBulkLength(redisClient *c, void *node, long length); -void addReplySds(redisClient *c, sds s); void processInputBuffer(redisClient *c); +void acceptHandler(aeEventLoop *el, int fd, void *privdata, int mask); void acceptTcpHandler(aeEventLoop *el, int fd, void *privdata, int mask); void acceptUnixHandler(aeEventLoop *el, int fd, void *privdata, int mask); void readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask); @@ -1011,7 +1010,6 @@ void addReplyBulk(redisClient *c, robj *obj); void addReplyBulkCString(redisClient *c, char *s); void addReplyBulkCBuffer(redisClient *c, void *p, size_t len); void addReplyBulkLongLong(redisClient *c, long long ll); -void acceptHandler(aeEventLoop *el, int fd, void *privdata, int mask); void addReply(redisClient *c, robj *obj); void addReplySds(redisClient *c, sds s); void addReplyError(redisClient *c, char *err); From cf85b5ba812070442c450b5dbc6c5e12a6c0819b Mon Sep 17 00:00:00 2001 From: Pieter Noordhuis Date: Wed, 10 Jul 2013 21:12:46 -0700 Subject: [PATCH 37/59] va_copy must be matched by va_end Hat tip to @rfuchs. See: https://github.com/redis/hiredis/pull/178. Fixes #1187 --- src/sds.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sds.c b/src/sds.c index dc07d0d3..fee627b9 100644 --- a/src/sds.c +++ b/src/sds.c @@ -388,6 +388,7 @@ sds sdscatvprintf(sds s, const char *fmt, va_list ap) { buf[buflen-2] = '\0'; va_copy(cpy,ap); vsnprintf(buf, buflen, fmt, cpy); + va_end(ap); if (buf[buflen-2] != '\0') { if (buf != staticbuf) zfree(buf); buflen *= 2; From 68db7b1f564be07fa98f6102aefb33d941fc2cdc Mon Sep 17 00:00:00 2001 From: antirez Date: Tue, 12 Aug 2014 15:17:28 +0200 Subject: [PATCH 38/59] Use unsigned integers in SDS header. This raises the max string to 4GB without any downside. --- deps/hiredis/sds.c | 9 ++++++--- deps/hiredis/sds.h | 4 ++-- src/sds.c | 7 +++++-- src/sds.h | 4 ++-- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/deps/hiredis/sds.c b/deps/hiredis/sds.c index 47b9823e..4af9961a 100644 --- a/deps/hiredis/sds.c +++ b/deps/hiredis/sds.c @@ -123,7 +123,7 @@ void sdsclear(sds s) { /* Enlarge the free space at the end of the sds string so that the caller * is sure that after calling this function can overwrite up to addlen * bytes after the end of the string, plus one more byte for nul term. - * + * * Note: this does not change the *length* of the sds string as returned * by sdslen(), but only the free buffer space we have. */ sds sdsMakeRoomFor(sds s, size_t addlen) { @@ -200,7 +200,10 @@ size_t sdsAllocSize(sds s) { void sdsIncrLen(sds s, int incr) { struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr))); - assert(sh->free >= incr); + if (incr >= 0) + assert(sh->free >= (unsigned int)incr); + else + assert(sh->len >= (unsigned int)(-incr)); sh->len += incr; sh->free -= incr; assert(sh->free >= 0); @@ -457,7 +460,7 @@ sds sdscatfmt(sds s, char const *fmt, ...) { i = initlen; /* Position of the next byte to write to dest str. */ while(*f) { char next, *str; - int l; + unsigned int l; long long num; unsigned long long unum; diff --git a/deps/hiredis/sds.h b/deps/hiredis/sds.h index 9a604021..37aaf7a2 100644 --- a/deps/hiredis/sds.h +++ b/deps/hiredis/sds.h @@ -39,8 +39,8 @@ typedef char *sds; struct sdshdr { - int len; - int free; + unsigned int len; + unsigned int free; char buf[]; }; diff --git a/src/sds.c b/src/sds.c index fee627b9..4adcc06a 100644 --- a/src/sds.c +++ b/src/sds.c @@ -200,7 +200,10 @@ size_t sdsAllocSize(sds s) { void sdsIncrLen(sds s, int incr) { struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr))); - assert(sh->free >= incr); + if (incr >= 0) + assert(sh->free >= (unsigned int)incr); + else + assert(sh->len >= (unsigned int)(-incr)); sh->len += incr; sh->free -= incr; assert(sh->free >= 0); @@ -458,7 +461,7 @@ sds sdscatfmt(sds s, char const *fmt, ...) { i = initlen; /* Position of the next byte to write to dest str. */ while(*f) { char next, *str; - int l; + unsigned int l; long long num; unsigned long long unum; diff --git a/src/sds.h b/src/sds.h index 9a604021..37aaf7a2 100644 --- a/src/sds.h +++ b/src/sds.h @@ -39,8 +39,8 @@ typedef char *sds; struct sdshdr { - int len; - int free; + unsigned int len; + unsigned int free; char buf[]; }; From 7e3ccddc6d728250dd473c1ab4348d899ab69eb3 Mon Sep 17 00:00:00 2001 From: antirez Date: Wed, 13 Aug 2014 10:53:29 +0200 Subject: [PATCH 39/59] Add -W to compilation flags. --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index b2d25228..96af74af 100644 --- a/src/Makefile +++ b/src/Makefile @@ -19,7 +19,7 @@ DEPENDENCY_TARGETS=hiredis linenoise lua # Default settings STD=-std=c99 -pedantic -WARN=-Wall +WARN=-Wall -W OPT=$(OPTIMIZATION) PREFIX?=/usr/local From edca2b14d213c31da9e7a919f6b898f3ea8abea8 Mon Sep 17 00:00:00 2001 From: antirez Date: Wed, 13 Aug 2014 11:44:38 +0200 Subject: [PATCH 40/59] Remove warnings and improve integer sign correctness. --- src/anet.c | 2 ++ src/aof.c | 9 ++++++++- src/bitops.c | 20 +++++++++++--------- src/cluster.c | 6 +++--- src/config.c | 2 +- src/db.c | 8 ++------ src/dict.c | 4 ++-- src/dict.h | 2 +- src/hyperloglog.c | 4 ++-- src/latency.c | 1 + src/networking.c | 2 +- src/redis-benchmark.c | 4 ++-- src/redis-cli.c | 9 +++++---- src/redis.c | 16 ++++++++-------- src/redis.h | 4 ++-- src/scripting.c | 2 +- src/sentinel.c | 19 ++++++++++++++----- 17 files changed, 66 insertions(+), 48 deletions(-) diff --git a/src/anet.c b/src/anet.c index c053ccf8..76915326 100644 --- a/src/anet.c +++ b/src/anet.c @@ -117,6 +117,8 @@ int anetKeepAlive(char *err, int fd, int interval) anetSetError(err, "setsockopt TCP_KEEPCNT: %s\n", strerror(errno)); return ANET_ERR; } +#else + ((void) interval); /* Avoid unused var warning for non Linux systems. */ #endif return ANET_OK; diff --git a/src/aof.c b/src/aof.c index a2ef2df9..5d46a21c 100644 --- a/src/aof.c +++ b/src/aof.c @@ -95,6 +95,10 @@ void aofChildWriteDiffData(aeEventLoop *el, int fd, void *privdata, int mask) { listNode *ln; aofrwblock *block; ssize_t nwritten; + REDIS_NOTUSED(el); + REDIS_NOTUSED(fd); + REDIS_NOTUSED(privdata); + REDIS_NOTUSED(mask); while(1) { ln = listFirst(server.aof_rewrite_buf_blocks); @@ -177,7 +181,7 @@ ssize_t aofRewriteBufferWrite(int fd) { if (block->used) { nwritten = write(fd,block->buf,block->used); - if (nwritten != block->used) { + if (nwritten != (ssize_t)block->used) { if (nwritten == 0) errno = EIO; return -1; } @@ -1128,6 +1132,9 @@ werr: * parent sends a '!' as well to acknowledge. */ void aofChildPipeReadable(aeEventLoop *el, int fd, void *privdata, int mask) { char byte; + REDIS_NOTUSED(el); + REDIS_NOTUSED(privdata); + REDIS_NOTUSED(mask); if (read(fd,&byte,1) == 1 && byte == '!') { redisLog(REDIS_NOTICE,"AOF rewrite child asks to stop sending diffs."); diff --git a/src/bitops.c b/src/bitops.c index 28f77243..94c7f353 100644 --- a/src/bitops.c +++ b/src/bitops.c @@ -107,12 +107,12 @@ size_t redisPopcount(void *s, long count) { * no zero bit is found, it returns count*8 assuming the string is zero * padded on the right. However if 'bit' is 1 it is possible that there is * not a single set bit in the bitmap. In this special case -1 is returned. */ -long redisBitpos(void *s, long count, int bit) { +long redisBitpos(void *s, unsigned long count, int bit) { unsigned long *l; unsigned char *c; unsigned long skipval, word = 0, one; long pos = 0; /* Position of bit, to return to the caller. */ - int j; + unsigned long j; /* Process whole words first, seeking for first word that is not * all ones or all zeros respectively if we are lookig for zeros @@ -276,11 +276,12 @@ void getbitCommand(redisClient *c) { void bitopCommand(redisClient *c) { char *opname = c->argv[1]->ptr; robj *o, *targetkey = c->argv[2]; - long op, j, numkeys; + unsigned long op, j, numkeys; robj **objects; /* Array of source objects. */ unsigned char **src; /* Array of source strings pointers. */ - long *len, maxlen = 0; /* Array of length of src strings, and max len. */ - long minlen = 0; /* Min len among the input keys. */ + unsigned long *len, maxlen = 0; /* Array of length of src strings, + and max len. */ + unsigned long minlen = 0; /* Min len among the input keys. */ unsigned char *res = NULL; /* Resulting string. */ /* Parse the operation name. */ @@ -320,9 +321,10 @@ void bitopCommand(redisClient *c) { } /* Return an error if one of the keys is not a string. */ if (checkType(c,o,REDIS_STRING)) { - for (j = j-1; j >= 0; j--) { - if (objects[j]) - decrRefCount(objects[j]); + unsigned long i; + for (i = 0; i < j; i++) { + if (objects[i]) + decrRefCount(objects[i]); } zfree(src); zfree(len); @@ -340,7 +342,7 @@ void bitopCommand(redisClient *c) { if (maxlen) { res = (unsigned char*) sdsnewlen(NULL,maxlen); unsigned char output, byte; - long i; + unsigned long i; /* Fast path: as far as we have data for all the input bitmaps we * can take a fast path that performs much better than the diff --git a/src/cluster.c b/src/cluster.c index 81f82f93..005a6ba5 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -323,7 +323,7 @@ int clusterSaveConfig(int do_fsync) { /* Pad the new payload if the existing file length is greater. */ if (fstat(fd,&sb) != -1) { - if (sb.st_size > content_size) { + if (sb.st_size > (off_t)content_size) { ci = sdsgrowzero(ci,sb.st_size); memset(ci+content_size,'\n',sb.st_size-content_size); } @@ -1907,7 +1907,7 @@ void clusterReadHandler(aeEventLoop *el, int fd, void *privdata, int mask) { ssize_t nread; clusterMsg *hdr; clusterLink *link = (clusterLink*) privdata; - int readlen, rcvbuflen; + unsigned int readlen, rcvbuflen; REDIS_NOTUSED(el); REDIS_NOTUSED(mask); @@ -3982,7 +3982,7 @@ void clusterCommand(redisClient *c) { "configEpoch set to %llu via CLUSTER SET-CONFIG-EPOCH", (unsigned long long) myself->configEpoch); - if (server.cluster->currentEpoch < epoch) + if (server.cluster->currentEpoch < (uint64_t)epoch) server.cluster->currentEpoch = epoch; /* No need to fsync the config here since in the unlucky event * of a failure to persist the config, the conflict resolution code diff --git a/src/config.c b/src/config.c index 04246fcb..2aff1351 100644 --- a/src/config.c +++ b/src/config.c @@ -629,7 +629,7 @@ void configSetCommand(redisClient *c) { server.maxclients = orig_value; return; } - if (aeGetSetSize(server.el) < + if ((unsigned int) aeGetSetSize(server.el) < server.maxclients + REDIS_EVENTLOOP_FDSET_INCR) { if (aeResizeSetSize(server.el, diff --git a/src/db.c b/src/db.c index e665008e..8eb1b89a 100644 --- a/src/db.c +++ b/src/db.c @@ -421,9 +421,7 @@ int parseScanCursorOrReply(redisClient *c, robj *o, unsigned long *cursor) { * In the case of a Hash object the function returns both the field and value * of every element on the Hash. */ void scanGenericCommand(redisClient *c, robj *o, unsigned long cursor) { - int rv; int i, j; - char buf[REDIS_LONGSTR_SIZE]; list *keys = listCreate(); listNode *node, *nextnode; long count = 10; @@ -503,7 +501,7 @@ void scanGenericCommand(redisClient *c, robj *o, unsigned long cursor) { privdata[1] = o; do { cursor = dictScan(ht, cursor, scanCallback, privdata); - } while (cursor && listLength(keys) < count); + } while (cursor && listLength(keys) < (unsigned long)count); } else if (o->type == REDIS_SET) { int pos = 0; int64_t ll; @@ -577,9 +575,7 @@ void scanGenericCommand(redisClient *c, robj *o, unsigned long cursor) { /* Step 4: Reply to the client. */ addReplyMultiBulkLen(c, 2); - rv = snprintf(buf, sizeof(buf), "%lu", cursor); - redisAssert(rv < sizeof(buf)); - addReplyBulkCBuffer(c, buf, rv); + addReplyBulkLongLong(c,cursor); addReplyMultiBulkLen(c, listLength(keys)); while ((node = listFirst(keys)) != NULL) { diff --git a/src/dict.c b/src/dict.c index b27920a4..42e75fc2 100644 --- a/src/dict.c +++ b/src/dict.c @@ -668,9 +668,9 @@ dictEntry *dictGetRandomKey(dict *d) * statistics. However the function is much faster than dictGetRandomKey() * at producing N elements, and the elements are guaranteed to be non * repeating. */ -int dictGetRandomKeys(dict *d, dictEntry **des, int count) { +unsigned int dictGetRandomKeys(dict *d, dictEntry **des, unsigned int count) { int j; /* internal hash table id, 0 or 1. */ - int stored = 0; + unsigned int stored = 0; if (dictSize(d) < count) count = dictSize(d); while(stored < count) { diff --git a/src/dict.h b/src/dict.h index 905330f5..042eb54f 100644 --- a/src/dict.h +++ b/src/dict.h @@ -162,7 +162,7 @@ dictIterator *dictGetSafeIterator(dict *d); dictEntry *dictNext(dictIterator *iter); void dictReleaseIterator(dictIterator *iter); dictEntry *dictGetRandomKey(dict *d); -int dictGetRandomKeys(dict *d, dictEntry **des, int count); +unsigned int dictGetRandomKeys(dict *d, dictEntry **des, unsigned int count); void dictPrintStats(dict *d); unsigned int dictGenHashFunction(const void *key, int len); unsigned int dictGenCaseHashFunction(const unsigned char *buf, int len); diff --git a/src/hyperloglog.c b/src/hyperloglog.c index 63052a78..005beb18 100644 --- a/src/hyperloglog.c +++ b/src/hyperloglog.c @@ -1349,7 +1349,7 @@ void pfmergeCommand(redisClient *c) { * Something that is not easy to test from within the outside. */ #define HLL_TEST_CYCLES 1000 void pfselftestCommand(redisClient *c) { - int j, i; + unsigned int j, i; sds bitcounters = sdsnewlen(NULL,HLL_DENSE_SIZE); struct hllhdr *hdr = (struct hllhdr*) bitcounters, *hdr2; robj *o = NULL; @@ -1431,7 +1431,7 @@ void pfselftestCommand(redisClient *c) { if (j == 10) maxerr = 1; if (abserr < 0) abserr = -abserr; - if (abserr > maxerr) { + if (abserr > (int64_t)maxerr) { addReplyErrorFormat(c, "TESTFAILED Too big error. card:%llu abserr:%llu", (unsigned long long) checkpoint, diff --git a/src/latency.c b/src/latency.c index fdc88210..b7845ca2 100644 --- a/src/latency.c +++ b/src/latency.c @@ -37,6 +37,7 @@ /* Dictionary type for latency events. */ int dictStringKeyCompare(void *privdata, const void *key1, const void *key2) { + REDIS_NOTUSED(privdata); return strcmp(key1,key2) == 0; } diff --git a/src/networking.c b/src/networking.c index 9c100db1..fb49b796 100644 --- a/src/networking.c +++ b/src/networking.c @@ -1051,7 +1051,7 @@ int processMultibulkBuffer(redisClient *c) { qblen = sdslen(c->querybuf); /* Hint the sds library about the amount of bytes this string is * going to contain. */ - if (qblen < ll+2) + if (qblen < (size_t)ll+2) c->querybuf = sdsMakeRoomFor(c->querybuf,ll+2-qblen); } c->bulklen = ll; diff --git a/src/redis-benchmark.c b/src/redis-benchmark.c index 5ab2625d..e6d6f573 100644 --- a/src/redis-benchmark.c +++ b/src/redis-benchmark.c @@ -213,7 +213,7 @@ static void readHandler(aeEventLoop *el, int fd, void *privdata, int mask) { freeReplyObject(reply); if (c->selectlen) { - int j; + size_t j; /* This is the OK from SELECT. Just discard the SELECT * from the buffer. */ @@ -359,7 +359,7 @@ static client createClient(char *cmd, size_t len, client from) { c->randfree = 0; c->randptr = zmalloc(sizeof(char*)*c->randlen); /* copy the offsets. */ - for (j = 0; j < c->randlen; j++) { + for (j = 0; j < (int)c->randlen; j++) { c->randptr[j] = c->obuf + (from->randptr[j]-from->obuf); /* Adjust for the different select prefix length. */ c->randptr[j] += c->selectlen - from->selectlen; diff --git a/src/redis-cli.c b/src/redis-cli.c index 43a35560..2e13d306 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -1416,7 +1416,7 @@ static int toIntType(char *key, char *type) { static void getKeyTypes(redisReply *keys, int *types) { redisReply *reply; - int i; + unsigned int i; /* Pipeline TYPE commands */ for(i=0;ielements;i++) { @@ -1445,7 +1445,7 @@ static void getKeySizes(redisReply *keys, int *types, { redisReply *reply; char *sizecmds[] = {"STRLEN","LLEN","SCARD","HLEN","ZCARD"}; - int i; + unsigned int i; /* Pipeline size commands */ for(i=0;ielements;i++) { @@ -1492,7 +1492,8 @@ static void findBigKeys(void) { char *typename[] = {"string","list","set","hash","zset"}; char *typeunit[] = {"bytes","items","members","fields","members"}; redisReply *reply, *keys; - int type, *types=NULL, arrsize=0, i; + unsigned int arrsize=0, i; + int type, *types=NULL; double pct; /* Total keys pre scanning */ @@ -1779,7 +1780,7 @@ static void scanMode(void) { printf("ERROR: %s\n", reply->str); exit(1); } else { - int j; + unsigned int j; cur = strtoull(reply->element[0]->str,NULL,10); for (j = 0; j < reply->element[1]->elements; j++) diff --git a/src/redis.c b/src/redis.c index ff4cbb17..e2df4882 100644 --- a/src/redis.c +++ b/src/redis.c @@ -760,8 +760,8 @@ void activeExpireCycle(int type) { static int timelimit_exit = 0; /* Time limit hit in previous call? */ static long long last_fast_cycle = 0; /* When last fast cycle ran. */ - unsigned int j, iteration = 0; - unsigned int dbs_per_call = REDIS_DBCRON_DBS_PER_CALL; + int j, iteration = 0; + int dbs_per_call = REDIS_DBCRON_DBS_PER_CALL; long long start = ustime(), timelimit; if (type == ACTIVE_EXPIRE_CYCLE_FAST) { @@ -1000,8 +1000,8 @@ void databasesCron(void) { * cron loop iteration. */ static unsigned int resize_db = 0; static unsigned int rehash_db = 0; - unsigned int dbs_per_call = REDIS_DBCRON_DBS_PER_CALL; - unsigned int j; + int dbs_per_call = REDIS_DBCRON_DBS_PER_CALL; + int j; /* Don't test more DBs than we have. */ if (dbs_per_call > server.dbnum) dbs_per_call = server.dbnum; @@ -1557,7 +1557,7 @@ void adjustOpenFilesLimit(void) { * to the higher value supported less than maxfiles. */ f = maxfiles; while(f > oldlimit) { - int decr_step = 16; + rlim_t decr_step = 16; limit.rlim_cur = f; limit.rlim_max = f; @@ -2359,9 +2359,9 @@ int time_independent_strcmp(char *a, char *b) { * a or b are fixed (our password) length, and the difference is only * relative to the length of the user provided string, so no information * leak is possible in the following two lines of code. */ - int alen = strlen(a); - int blen = strlen(b); - int j; + unsigned int alen = strlen(a); + unsigned int blen = strlen(b); + unsigned int j; int diff = 0; /* We can't compare strings longer than our static buffers. diff --git a/src/redis.h b/src/redis.h index 75c353fc..c352cd79 100644 --- a/src/redis.h +++ b/src/redis.h @@ -814,12 +814,12 @@ struct redisServer { /* Replication script cache. */ dict *repl_scriptcache_dict; /* SHA1 all slaves are aware of. */ list *repl_scriptcache_fifo; /* First in, first out LRU eviction. */ - int repl_scriptcache_size; /* Max number of elements. */ + unsigned int repl_scriptcache_size; /* Max number of elements. */ /* Synchronous replication. */ list *clients_waiting_acks; /* Clients waiting in WAIT command. */ int get_ack_from_slaves; /* If true we send REPLCONF GETACK. */ /* Limits */ - int maxclients; /* Max number of simultaneous clients */ + unsigned int maxclients; /* Max number of simultaneous clients */ unsigned long long maxmemory; /* Max number of memory bytes to use */ int maxmemory_policy; /* Policy for key eviction */ int maxmemory_samples; /* Pricision of random sampling */ diff --git a/src/scripting.c b/src/scripting.c index 0a511e98..a0c88742 100644 --- a/src/scripting.c +++ b/src/scripting.c @@ -212,7 +212,7 @@ int luaRedisGenericCommand(lua_State *lua, int raise_error) { static robj **argv = NULL; static int argv_size = 0; static robj *cached_objects[LUA_CMD_OBJCACHE_SIZE]; - static int cached_objects_len[LUA_CMD_OBJCACHE_SIZE]; + static size_t cached_objects_len[LUA_CMD_OBJCACHE_SIZE]; /* Require at least one argument */ if (argc == 0) { diff --git a/src/sentinel.c b/src/sentinel.c index 48e1de8d..61ca3000 100644 --- a/src/sentinel.c +++ b/src/sentinel.c @@ -159,7 +159,7 @@ typedef struct sentinelRedisInstance { /* Master specific. */ dict *sentinels; /* Other sentinels monitoring the same master. */ dict *slaves; /* Slaves for this master instance. */ - int quorum; /* Number of sentinels that need to agree on failure. */ + unsigned int quorum;/* Number of sentinels that need to agree on failure. */ int parallel_syncs; /* How many slaves to reconfigure at same time. */ char *auth_pass; /* Password to use for AUTH against master & slaves. */ @@ -345,6 +345,7 @@ int dictSdsKeyCompare(void *privdata, const void *key1, const void *key2); void releaseSentinelRedisInstance(sentinelRedisInstance *ri); void dictInstancesValDestructor (void *privdata, void *obj) { + REDIS_NOTUSED(privdata); releaseSentinelRedisInstance(obj); } @@ -403,7 +404,7 @@ void initSentinelConfig(void) { /* Perform the Sentinel mode initialization. */ void initSentinel(void) { - int j; + unsigned int j; /* Remove usual Redis commands from the command table, then just add * the SENTINEL command. */ @@ -1634,6 +1635,7 @@ void sentinelLinkEstablishedCallback(const redisAsyncContext *c, int status) { } void sentinelDisconnectCallback(const redisAsyncContext *c, int status) { + REDIS_NOTUSED(status); sentinelDisconnectInstanceFromContext(c); } @@ -1998,6 +2000,7 @@ void sentinelRefreshInstanceInfo(sentinelRedisInstance *ri, const char *info) { void sentinelInfoReplyCallback(redisAsyncContext *c, void *reply, void *privdata) { sentinelRedisInstance *ri = c->data; redisReply *r; + REDIS_NOTUSED(privdata); if (ri) ri->pending_commands--; if (!reply || !ri) return; @@ -2012,6 +2015,8 @@ void sentinelInfoReplyCallback(redisAsyncContext *c, void *reply, void *privdata * value of the command but its effects directly. */ void sentinelDiscardReplyCallback(redisAsyncContext *c, void *reply, void *privdata) { sentinelRedisInstance *ri = c->data; + REDIS_NOTUSED(reply); + REDIS_NOTUSED(privdata); if (ri) ri->pending_commands--; } @@ -2019,6 +2024,7 @@ void sentinelDiscardReplyCallback(redisAsyncContext *c, void *reply, void *privd void sentinelPingReplyCallback(redisAsyncContext *c, void *reply, void *privdata) { sentinelRedisInstance *ri = c->data; redisReply *r; + REDIS_NOTUSED(privdata); if (ri) ri->pending_commands--; if (!reply || !ri) return; @@ -2057,6 +2063,7 @@ void sentinelPingReplyCallback(redisAsyncContext *c, void *reply, void *privdata void sentinelPublishReplyCallback(redisAsyncContext *c, void *reply, void *privdata) { sentinelRedisInstance *ri = c->data; redisReply *r; + REDIS_NOTUSED(privdata); if (ri) ri->pending_commands--; if (!reply || !ri) return; @@ -2166,6 +2173,7 @@ cleanup: void sentinelReceiveHelloMessages(redisAsyncContext *c, void *reply, void *privdata) { sentinelRedisInstance *ri = c->data; redisReply *r; + REDIS_NOTUSED(privdata); if (!reply || !ri) return; r = reply; @@ -2559,7 +2567,7 @@ sentinelRedisInstance *sentinelGetMasterByNameOrReplyError(redisClient *c, { sentinelRedisInstance *ri; - ri = dictFetchValue(sentinel.masters,c->argv[2]->ptr); + ri = dictFetchValue(sentinel.masters,name->ptr); if (!ri) { addReplyError(c,"No such master with that name"); return NULL; @@ -2997,7 +3005,7 @@ void sentinelCheckSubjectivelyDown(sentinelRedisInstance *ri) { void sentinelCheckObjectivelyDown(sentinelRedisInstance *master) { dictIterator *di; dictEntry *de; - int quorum = 0, odown = 0; + unsigned int quorum = 0, odown = 0; if (master->flags & SRI_S_DOWN) { /* Is down for enough sentinels? */ @@ -3034,6 +3042,7 @@ void sentinelCheckObjectivelyDown(sentinelRedisInstance *master) { void sentinelReceiveIsMasterDownReply(redisAsyncContext *c, void *reply, void *privdata) { sentinelRedisInstance *ri = c->data; redisReply *r; + REDIS_NOTUSED(privdata); if (ri) ri->pending_commands--; if (!reply || !ri) return; @@ -3057,7 +3066,7 @@ void sentinelReceiveIsMasterDownReply(redisAsyncContext *c, void *reply, void *p /* If the runid in the reply is not "*" the Sentinel actually * replied with a vote. */ sdsfree(ri->leader); - if (ri->leader_epoch != r->element[2]->integer) + if ((long long)ri->leader_epoch != r->element[2]->integer) redisLog(REDIS_WARNING, "%s voted for %s %llu", ri->name, r->element[1]->str, From 6a7a32a806aa7a10239803293a04966d75409942 Mon Sep 17 00:00:00 2001 From: Matt Stancliff Date: Fri, 1 Aug 2014 16:42:02 -0400 Subject: [PATCH 41/59] Clarify existing slot wording on cluster start --- src/cluster.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/cluster.c b/src/cluster.c index 005a6ba5..3b3d2682 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -3289,14 +3289,13 @@ int verifyClusterConfigWithData(void) { update_config++; /* Case A: slot is unassigned. Take responsability for it. */ if (server.cluster->slots[j] == NULL) { - redisLog(REDIS_WARNING, "I've keys about slot %d that is " - "unassigned. Taking responsability " - "for it.",j); + redisLog(REDIS_WARNING, "I have keys for unassigned slot %d. " + "Taking responsibility for it.",j); clusterAddSlot(myself,j); } else { - redisLog(REDIS_WARNING, "I've keys about slot %d that is " - "already assigned to a different node. " - "Setting it in importing state.",j); + redisLog(REDIS_WARNING, "I have keys for slot %d, but the slot is " + "assigned to another node. " + "Setting it to importing state.",j); server.cluster->importing_slots_from[j] = server.cluster->slots[j]; } } From d786fb6e94fab0204a05caa0966fc2a37d9168ee Mon Sep 17 00:00:00 2001 From: xiaoyu Date: Fri, 18 May 2012 20:34:10 +0800 Subject: [PATCH 42/59] Clarify argument to dict macro d is more clear because the type of argument is dict not dictht Closes #513 --- src/dict.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dict.h b/src/dict.h index 042eb54f..b82e137f 100644 --- a/src/dict.h +++ b/src/dict.h @@ -142,7 +142,7 @@ typedef void (dictScanFunction)(void *privdata, const dictEntry *de); #define dictGetDoubleVal(he) ((he)->v.d) #define dictSlots(d) ((d)->ht[0].size+(d)->ht[1].size) #define dictSize(d) ((d)->ht[0].used+(d)->ht[1].used) -#define dictIsRehashing(ht) ((ht)->rehashidx != -1) +#define dictIsRehashing(d) ((d)->rehashidx != -1) /* API */ dict *dictCreate(dictType *type, void *privDataPtr); From 233d24a7378f3ef59baa7aa593278338c8e9d0d9 Mon Sep 17 00:00:00 2001 From: Dov Murik Date: Wed, 26 Dec 2012 22:00:08 +0200 Subject: [PATCH 43/59] redis-cli: fix prompt after shutdown command Fix redis-cli prompt to state "not connected" after a SHUTDOWN command is sent. --- src/redis-cli.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/redis-cli.c b/src/redis-cli.c index 2e13d306..3526319d 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -517,8 +517,11 @@ static int cliReadReply(int output_raw_strings) { int output = 1; if (redisGetReply(context,&_reply) != REDIS_OK) { - if (config.shutdown) + if (config.shutdown) { + redisFree(context); + context = NULL; return REDIS_OK; + } if (config.interactive) { /* Filter cases where we should reconnect */ if (context->err == REDIS_ERR_IO && errno == ECONNRESET) From 0a98b21f657b2bfc822619c33bb8f9991df742d6 Mon Sep 17 00:00:00 2001 From: yoav Date: Mon, 31 Dec 2012 00:44:30 +0200 Subject: [PATCH 44/59] Add error check for writing RDB checksum Closes #857 --- src/rdb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rdb.c b/src/rdb.c index 89e77e6f..afaef268 100644 --- a/src/rdb.c +++ b/src/rdb.c @@ -688,7 +688,7 @@ int rdbSave(char *filename) { * loading code skips the check in this case. */ cksum = rdb.cksum; memrev64ifbe(&cksum); - rioWrite(&rdb,&cksum,8); + if (rioWrite(&rdb,&cksum,8) == 0) goto werr; /* Make sure data will not remain on the OS's output buffers */ if (fflush(fp) == EOF) goto werr; From 100c3315be5faafbdaa3fdcc5f302a5d599f0cd0 Mon Sep 17 00:00:00 2001 From: David Palm Date: Wed, 2 Jan 2013 20:22:26 +0100 Subject: [PATCH 45/59] Extend range of bytesToHuman to TB and PB Also adds a fallthrough case for when given large values (like overflow numbers of 2^64 by mistake). Closes #858 --- src/redis.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/redis.c b/src/redis.c index e2df4882..6a2e95e9 100644 --- a/src/redis.c +++ b/src/redis.c @@ -2547,6 +2547,15 @@ void bytesToHuman(char *s, unsigned long long n) { } else if (n < (1024LL*1024*1024*1024)) { d = (double)n/(1024LL*1024*1024); sprintf(s,"%.2fG",d); + } else if (n < (1024LL*1024*1024*1024*1024)) { + d = (double)n/(1024LL*1024*1024*1024); + sprintf(s,"%.2fT",d); + } else if (n < (1024LL*1024*1024*1024*1024*1024)) { + d = (double)n/(1024LL*1024*1024*1024*1024); + sprintf(s,"%.2fP",d); + } else { + /* Let's hope we never need this */ + sprintf(s,"%lluB",n); } } From 18ca831830b3fdcae0c3aade84c88d4204db6533 Mon Sep 17 00:00:00 2001 From: Cong Ding Date: Sun, 13 Jan 2013 23:21:06 +0100 Subject: [PATCH 46/59] Remove unused function Closes #878 --- src/dict.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/dict.c b/src/dict.c index 42e75fc2..17818b85 100644 --- a/src/dict.c +++ b/src/dict.c @@ -79,12 +79,6 @@ unsigned int dictIntHashFunction(unsigned int key) return key; } -/* Identity hash function for integer keys */ -unsigned int dictIdentityHashFunction(unsigned int key) -{ - return key; -} - static uint32_t dict_hash_function_seed = 5381; void dictSetHashFunctionSeed(uint32_t seed) { From a6edfceaa876ac6f21d7995aaf2380ab0eb50cbe Mon Sep 17 00:00:00 2001 From: antirez Date: Mon, 18 Aug 2014 11:15:50 +0200 Subject: [PATCH 47/59] Fix invalid expire error for SET family commands. --- src/t_string.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/t_string.c b/src/t_string.c index 397363c5..8a4d5f16 100644 --- a/src/t_string.c +++ b/src/t_string.c @@ -69,7 +69,7 @@ void setGenericCommand(redisClient *c, int flags, robj *key, robj *val, robj *ex if (getLongLongFromObjectOrReply(c, expire, &milliseconds, NULL) != REDIS_OK) return; if (milliseconds <= 0) { - addReplyError(c,"invalid expire time in SETEX"); + addReplyErrorFormat(c,"invalid expire time in %s",c->cmd->name); return; } if (unit == UNIT_SECONDS) milliseconds *= 1000; From 82bac1b7297fa877f1b788f8d29ac6261616715a Mon Sep 17 00:00:00 2001 From: Matt Stancliff Date: Fri, 1 Aug 2014 21:06:26 -0400 Subject: [PATCH 48/59] Remove unused global variable It has an important name, but nothing uses it... --- src/redis.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/redis.c b/src/redis.c index 6a2e95e9..c1b26959 100644 --- a/src/redis.c +++ b/src/redis.c @@ -66,7 +66,6 @@ double R_Zero, R_PosInf, R_NegInf, R_Nan; /* Global vars */ struct redisServer server; /* server global state */ -struct redisCommand *commandTable; /* Our command table. * From 879e18b7ec9728f52fb79eae99f8403ae3372096 Mon Sep 17 00:00:00 2001 From: Matt Stancliff Date: Fri, 1 Aug 2014 21:48:12 -0400 Subject: [PATCH 49/59] Fix memory leak in cluster config parsing The continue stop us from triggering the free after the long line for loop, so add it earlier. --- src/cluster.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cluster.c b/src/cluster.c index 3b3d2682..b3d9b6a7 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -164,6 +164,7 @@ int clusterLoadConfig(char *filename) { argv[j]); } } + sdsfreesplitres(argv,argc); continue; } From 60c448b58469ea08aaae16b5667788cbd8044516 Mon Sep 17 00:00:00 2001 From: Matt Stancliff Date: Thu, 27 Mar 2014 12:33:42 -0400 Subject: [PATCH 50/59] Cluster: Fix segfault if cluster config corrupt This commit adds a size check after initial config line parsing to make sure we have *at least* 8 arguments per line. Also, instead of asserting for cluster->myself, we just test and error out normally (since the error does a hard exit anyway). Closes #1597 --- src/cluster.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/cluster.c b/src/cluster.c index b3d9b6a7..07eaa637 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -168,6 +168,9 @@ int clusterLoadConfig(char *filename) { continue; } + /* Regular config lines have at least eight fields */ + if (argc < 8) goto fmterr; + /* Create this node if it does not exist */ n = clusterLookupNode(argv[0]); if (!n) { @@ -268,11 +271,12 @@ int clusterLoadConfig(char *filename) { sdsfreesplitres(argv,argc); } + /* Config sanity check */ + if (server.cluster->myself == NULL) goto fmterr; + zfree(line); fclose(fp); - /* Config sanity check */ - redisAssert(server.cluster->myself != NULL); redisLog(REDIS_NOTICE,"Node configuration loaded, I'm %.40s", myself->name); /* Something that should never happen: currentEpoch smaller than @@ -287,7 +291,7 @@ fmterr: redisLog(REDIS_WARNING, "Unrecoverable error: corrupted cluster config file."); zfree(line); - fclose(fp); + if (fp) fclose(fp); exit(1); } From 681de88df4814a4a6e794a07530a3865ef515d2c Mon Sep 17 00:00:00 2001 From: Matt Stancliff Date: Mon, 4 Aug 2014 12:28:45 -0400 Subject: [PATCH 51/59] Sentinel: Reject config from STDIN Sentinel needs to die with a more accurate error message when attempted to open a config from STDIN. See: https://groups.google.com/forum/#!topic/redis-db/sYx7VNMWaNM --- src/redis.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/redis.c b/src/redis.c index c1b26959..eb8bfbc6 100644 --- a/src/redis.c +++ b/src/redis.c @@ -3576,6 +3576,13 @@ int main(int argc, char **argv) { } j++; } + if (server.sentinel_mode && configfile && *configfile == '-') { + redisLog(REDIS_WARNING, + "Sentinel config from STDIN not allowed."); + redisLog(REDIS_WARNING, + "Sentinel needs config file on disk to save state. Exiting..."); + exit(1); + } if (configfile) server.configfile = getAbsolutePath(configfile); resetServerSaveParams(); loadServerConfig(configfile,options); From 5afe1e37c7f04224831d6e0e34579e4ce496d006 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariano=20P=C3=A9rez=20Rodr=C3=ADguez?= Date: Tue, 5 Aug 2014 09:50:44 -0300 Subject: [PATCH 52/59] Stop tests from leaving a black background Uses ANSI "default background" color code after closing tests so any non-black terminals don't remain polluted. Fixes #1649 Closes #1912 --- tests/support/util.tcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/support/util.tcl b/tests/support/util.tcl index 7774dd99..4b9caced 100644 --- a/tests/support/util.tcl +++ b/tests/support/util.tcl @@ -353,7 +353,7 @@ proc colorstr {color str} { default {set colorcode {37}} } if {$colorcode ne {}} { - return "\033\[$b;${colorcode};40m$str\033\[0m" + return "\033\[$b;${colorcode};49m$str\033\[0m" } } else { return $str From ef57f94df0c07ccdd61e537283f45f977840f8ad Mon Sep 17 00:00:00 2001 From: Jan-Erik Rediger Date: Tue, 5 Aug 2014 09:12:40 +0200 Subject: [PATCH 53/59] Use correct github url to find commands.json Once this is merged: - merge the latest changes to commands.json in antirez/redis-doc - re-run: utils/generate-command-help.rb > src/help.h Then we'll have nice and easy tab-completed help in redis-cli again. Closes #1909 --- utils/generate-command-help.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/generate-command-help.rb b/utils/generate-command-help.rb index 47fbc645..06895319 100755 --- a/utils/generate-command-help.rb +++ b/utils/generate-command-help.rb @@ -50,7 +50,7 @@ def commands require "json" require "uri" - url = URI.parse "https://raw.github.com/antirez/redis-doc/master/commands.json" + url = URI.parse "https://raw.githubusercontent.com/antirez/redis-doc/master/commands.json" client = Net::HTTP.new url.host, url.port client.use_ssl = true response = client.get url.path From c38884ceaca3b0be250d28b3a9e842328cde7d90 Mon Sep 17 00:00:00 2001 From: Eiichi Sato Date: Wed, 6 Aug 2014 14:48:30 +0900 Subject: [PATCH 54/59] Sentinel: fix bufsize to support IPv6 address Closes #1914 --- src/sentinel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sentinel.c b/src/sentinel.c index 61ca3000..e8630a9a 100644 --- a/src/sentinel.c +++ b/src/sentinel.c @@ -456,7 +456,7 @@ void sentinelIsRunning(void) { * EINVAL: Invalid port number. */ sentinelAddr *createSentinelAddr(char *hostname, int port) { - char buf[32]; + char buf[REDIS_IP_STR_LEN]; sentinelAddr *sa; if (port <= 0 || port > 65535) { @@ -2690,7 +2690,7 @@ void sentinelCommand(redisClient *c) { /* SENTINEL MONITOR */ sentinelRedisInstance *ri; long quorum, port; - char buf[32]; + char buf[REDIS_IP_STR_LEN]; if (c->argc != 6) goto numargserr; if (getLongFromObjectOrReply(c,c->argv[5],&quorum,"Invalid quorum") From 7e63dd23f3faae7a399617128ffef224e0f21754 Mon Sep 17 00:00:00 2001 From: Matt Stancliff Date: Wed, 6 Aug 2014 10:16:46 -0400 Subject: [PATCH 55/59] Rename two 'buf' vars to 'ip' for better clarity Clearly ip[32] is wrong, but it's less clear that buf[32] was wrong without further reading. --- src/sentinel.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sentinel.c b/src/sentinel.c index e8630a9a..603cdd40 100644 --- a/src/sentinel.c +++ b/src/sentinel.c @@ -456,19 +456,19 @@ void sentinelIsRunning(void) { * EINVAL: Invalid port number. */ sentinelAddr *createSentinelAddr(char *hostname, int port) { - char buf[REDIS_IP_STR_LEN]; + char ip[REDIS_IP_STR_LEN]; sentinelAddr *sa; if (port <= 0 || port > 65535) { errno = EINVAL; return NULL; } - if (anetResolve(NULL,hostname,buf,sizeof(buf)) == ANET_ERR) { + if (anetResolve(NULL,hostname,ip,sizeof(ip)) == ANET_ERR) { errno = ENOENT; return NULL; } sa = zmalloc(sizeof(*sa)); - sa->ip = sdsnew(buf); + sa->ip = sdsnew(ip); sa->port = port; return sa; } @@ -2690,7 +2690,7 @@ void sentinelCommand(redisClient *c) { /* SENTINEL MONITOR */ sentinelRedisInstance *ri; long quorum, port; - char buf[REDIS_IP_STR_LEN]; + char ip[REDIS_IP_STR_LEN]; if (c->argc != 6) goto numargserr; if (getLongFromObjectOrReply(c,c->argv[5],&quorum,"Invalid quorum") @@ -2700,7 +2700,7 @@ void sentinelCommand(redisClient *c) { /* Make sure the IP field is actually a valid IP before passing it * to createSentinelRedisInstance(), otherwise we may trigger a * DNS lookup at runtime. */ - if (anetResolveIP(NULL,c->argv[3]->ptr,buf,sizeof(buf)) == ANET_ERR) { + if (anetResolveIP(NULL,c->argv[3]->ptr,ip,sizeof(ip)) == ANET_ERR) { addReplyError(c,"Invalid IP address specified"); return; } From b34a8c3b754c97083e93f225e4dc6b262ff0a0de Mon Sep 17 00:00:00 2001 From: CharSyam Date: Thu, 9 May 2013 14:30:20 +0000 Subject: [PATCH 56/59] redis-benchmark: add auth option Closes #1097 --- src/redis-benchmark.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/redis-benchmark.c b/src/redis-benchmark.c index e6d6f573..d8b49a71 100644 --- a/src/redis-benchmark.c +++ b/src/redis-benchmark.c @@ -77,6 +77,7 @@ static struct config { int dbnum; sds dbnumstr; char *tests; + char *auth; } config; typedef struct _client { @@ -325,6 +326,13 @@ static client createClient(char *cmd, size_t len, client from) { * the example client buffer. */ c->obuf = sdsempty(); + if (config.auth) { + char *buf = NULL; + int len = redisFormatCommand(&buf, "AUTH %s", config.auth); + c->obuf = sdscatlen(c->obuf, buf, len); + free(buf); + } + /* If a DB number different than zero is selected, prefix our request * buffer with the SELECT command, that will be discarded the first * time the replies are received, so if the client is reused the @@ -346,6 +354,7 @@ static client createClient(char *cmd, size_t len, client from) { for (j = 0; j < config.pipeline; j++) c->obuf = sdscatlen(c->obuf,cmd,len); } + c->written = 0; c->pending = config.pipeline; c->randptr = NULL; @@ -489,6 +498,9 @@ int parseOptions(int argc, const char **argv) { } else if (!strcmp(argv[i],"-s")) { if (lastarg) goto invalid; config.hostsocket = strdup(argv[++i]); + } else if (!strcmp(argv[i],"-a") ) { + if (lastarg) goto invalid; + config.auth = strdup(argv[++i]); } else if (!strcmp(argv[i],"-d")) { if (lastarg) goto invalid; config.datasize = atoi(argv[++i]); @@ -550,6 +562,7 @@ usage: " -h Server hostname (default 127.0.0.1)\n" " -p Server port (default 6379)\n" " -s Server socket (overrides host and port)\n" +" -a Password for Redis Auth\n" " -c Number of parallel connections (default 50)\n" " -n Total number of requests (default 10000)\n" " -d Data size of SET/GET value in bytes (default 2)\n" @@ -651,6 +664,7 @@ int main(int argc, const char **argv) { config.hostsocket = NULL; config.tests = NULL; config.dbnum = 0; + config.auth = NULL; i = parseOptions(argc,argv); argc -= i; From aa404fc11be08f45fa0785c43f5fc7426e2b14a4 Mon Sep 17 00:00:00 2001 From: Matt Stancliff Date: Wed, 6 Aug 2014 10:40:34 -0400 Subject: [PATCH 57/59] redis-benchmark: Remove unused buffer This just deletes old code that didn't get removed when logic changed. We were setting offsets that never got read anywhere. Since clients are now just cloned, we don't need to track per-client buffer offsets anywhere because they are all the same from the original client. --- src/redis-benchmark.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/redis-benchmark.c b/src/redis-benchmark.c index d8b49a71..2e0aa8a6 100644 --- a/src/redis-benchmark.c +++ b/src/redis-benchmark.c @@ -398,15 +398,6 @@ static client createClient(char *cmd, size_t len, client from) { static void createMissingClients(client c) { int n = 0; - char *buf = c->obuf; - size_t buflen = sdslen(c->obuf); - - /* If we are cloning from a client with a SELECT prefix, skip it since the - * client will be created with the prefixed SELECT if needed. */ - if (c->selectlen) { - buf += c->selectlen; - buflen -= c->selectlen; - } while(config.liveclients < config.numclients) { createClient(NULL,0,c); From 6b099c7de614bebe3e61a0cbb91af459cc67f1c3 Mon Sep 17 00:00:00 2001 From: Matt Stancliff Date: Wed, 6 Aug 2014 16:56:23 -0400 Subject: [PATCH 58/59] Deny CLIENT command in scripts We don't want scripts doing CLIENT SETNAME or CLIENT KILL or CLIENT LIST or CLIENT PAUSE. Originally reported by Chris Wj then proper action inspired by Itamar Haber. Reference: https://groups.google.com/forum/#!topic/redis-db/09B2EYwyVgk --- src/redis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/redis.c b/src/redis.c index eb8bfbc6..e58ceb04 100644 --- a/src/redis.c +++ b/src/redis.c @@ -266,7 +266,7 @@ struct redisCommand redisCommandTable[] = { {"readwrite",readwriteCommand,1,"rF",0,NULL,0,0,0,0,0}, {"dump",dumpCommand,2,"ar",0,NULL,1,1,1,0,0}, {"object",objectCommand,3,"r",0,NULL,2,2,2,0,0}, - {"client",clientCommand,-2,"ar",0,NULL,0,0,0,0,0}, + {"client",clientCommand,-2,"ars",0,NULL,0,0,0,0,0}, {"eval",evalCommand,-3,"s",0,evalGetKeys,0,0,0,0,0}, {"evalsha",evalShaCommand,-3,"s",0,evalGetKeys,0,0,0,0,0}, {"slowlog",slowlogCommand,-2,"r",0,NULL,0,0,0,0,0}, From 1f8a6d806cc25ece4d092fb3d49af9ccc1443102 Mon Sep 17 00:00:00 2001 From: Matt Stancliff Date: Wed, 13 Aug 2014 10:58:54 -0400 Subject: [PATCH 59/59] Fix redis-benchmark abort output --- src/redis-benchmark.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/redis-benchmark.c b/src/redis-benchmark.c index 2e0aa8a6..2e67f102 100644 --- a/src/redis-benchmark.c +++ b/src/redis-benchmark.c @@ -597,7 +597,7 @@ int showThroughput(struct aeEventLoop *eventLoop, long long id, void *clientData REDIS_NOTUSED(clientData); if (config.liveclients == 0) { - fprintf(stderr,"All clients disconnected... aborting."); + fprintf(stderr,"All clients disconnected... aborting.\n"); exit(1); }