From d4d208595c78d78196c926c55799bc81ae06f230 Mon Sep 17 00:00:00 2001 From: antirez Date: Fri, 20 Jan 2012 12:20:45 +0100 Subject: [PATCH 1/7] all the stack trace related functions are now in debug.c. Now Redis dumps registers and stack content on crash. Currently osx supported, adding Linux right now. --- src/debug.c | 218 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/redis.c | 135 -------------------------------- src/redis.h | 3 +- 3 files changed, 220 insertions(+), 136 deletions(-) diff --git a/src/debug.c b/src/debug.c index 728aa8a1..59e15844 100644 --- a/src/debug.c +++ b/src/debug.c @@ -2,6 +2,12 @@ #include "sha1.h" /* SHA1 is used for DEBUG DIGEST */ #include +#include + +#ifdef HAVE_BACKTRACE +#include +#include +#endif /* HAVE_BACKTRACE */ /* ================================= Debugging ============================== */ @@ -297,6 +303,8 @@ void debugCommand(redisClient *c) { } } +/* =========================== Crash handling ============================== */ + void _redisAssert(char *estr, char *file, int line) { bugReportStart(); redisLog(REDIS_WARNING,"=== ASSERTION FAILED ==="); @@ -380,3 +388,213 @@ void _redisPanic(char *msg, char *file, int line) { *((char*)-1) = 'x'; #endif } + +#ifdef HAVE_BACKTRACE +static void *getMcontextEip(ucontext_t *uc) { +#if defined(__FreeBSD__) + return (void*) uc->uc_mcontext.mc_eip; +#elif defined(__dietlibc__) + return (void*) uc->uc_mcontext.eip; +#elif defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_6) + #if __x86_64__ + return (void*) uc->uc_mcontext->__ss.__rip; + #elif __i386__ + return (void*) uc->uc_mcontext->__ss.__eip; + #else + return (void*) uc->uc_mcontext->__ss.__srr0; + #endif +#elif defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_6) + #if defined(_STRUCT_X86_THREAD_STATE64) && !defined(__i386__) + return (void*) uc->uc_mcontext->__ss.__rip; + #else + return (void*) uc->uc_mcontext->__ss.__eip; + #endif +#elif defined(__i386__) + return (void*) uc->uc_mcontext.gregs[14]; /* Linux 32 */ +#elif defined(__X86_64__) || defined(__x86_64__) + return (void*) uc->uc_mcontext.gregs[16]; /* Linux 64 */ +#elif defined(__ia64__) /* Linux IA64 */ + return (void*) uc->uc_mcontext.sc_ip; +#else + return NULL; +#endif +} + +void bugReportStart(void) { + if (server.bug_report_start == 0) { + redisLog(REDIS_WARNING, + "\n\n=== REDIS BUG REPORT START: Cut & paste starting from here ==="); + server.bug_report_start = 1; + } +} + +void logStackContent(void **sp) { + int i; + for (i = 15; i >= 0; i--) { + redisLog(REDIS_WARNING, "(%p) -> %p", sp+i, sp[i]); + } +} + +void logRegisters(ucontext_t *uc) { + redisLog(REDIS_WARNING, "--- REGISTERS"); +#if defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_6) + #if defined(_STRUCT_X86_THREAD_STATE64) && !defined(__i386__) + redisLog(REDIS_WARNING, + "\n" + "RAX:%p RBX:%p RCX:%p RDX:%p\n" + "RDI:%p RSI:%p RBP:%p RSP:%p\n" + "R8:%p R9:%p R10:%p R11:%p\n" + "R12:%p R13:%p R14:%p R15:%p\n" + "RIP:%p EFL:%p CS:%p FS:%p GS:%p", + uc->uc_mcontext->__ss.__rax, + uc->uc_mcontext->__ss.__rbx, + uc->uc_mcontext->__ss.__rcx, + uc->uc_mcontext->__ss.__rdx, + uc->uc_mcontext->__ss.__rdi, + uc->uc_mcontext->__ss.__rsi, + uc->uc_mcontext->__ss.__rbp, + uc->uc_mcontext->__ss.__rsp, + uc->uc_mcontext->__ss.__r8, + uc->uc_mcontext->__ss.__r9, + uc->uc_mcontext->__ss.__r10, + uc->uc_mcontext->__ss.__r11, + uc->uc_mcontext->__ss.__r12, + uc->uc_mcontext->__ss.__r13, + uc->uc_mcontext->__ss.__r14, + uc->uc_mcontext->__ss.__r15, + uc->uc_mcontext->__ss.__rip, + uc->uc_mcontext->__ss.__rflags, + uc->uc_mcontext->__ss.__cs, + uc->uc_mcontext->__ss.__fs, + uc->uc_mcontext->__ss.__gs + ); + logStackContent((void**)uc->uc_mcontext->__ss.__rsp); + #else + redisLog(REDIS_WARNING, + "\n" + "EAX:%p EBX:%p ECX:%p EDX:%p\n" + "EDI:%p ESI:%p EBP:%p ESP:%p\n" + "SS:%p EFL:%p EIP:%p CS:%p\n" + "DS:%p ES:%p FS:%p GS:%p", + uc->uc_mcontext->__ss.__eax, + uc->uc_mcontext->__ss.__ebx, + uc->uc_mcontext->__ss.__ecx, + uc->uc_mcontext->__ss.__edx, + uc->uc_mcontext->__ss.__edi, + uc->uc_mcontext->__ss.__esi, + uc->uc_mcontext->__ss.__ebp, + uc->uc_mcontext->__ss.__esp, + uc->uc_mcontext->__ss.__ss, + uc->uc_mcontext->__ss.__eflags, + uc->uc_mcontext->__ss.__eip, + uc->uc_mcontext->__ss.__cs, + uc->uc_mcontext->__ss.__ds, + uc->uc_mcontext->__ss.__es, + uc->uc_mcontext->__ss.__fs, + uc->uc_mcontext->__ss.__gs + ); + logStackContent((void**)uc->uc_mcontext->__ss.__esp); + #endif +#elif defined(__i386__) + return (void*) uc->uc_mcontext.gregs[14]; /* Linux 32 */ +#elif defined(__X86_64__) || defined(__x86_64__) + return (void*) uc->uc_mcontext.gregs[16]; /* Linux 64 */ +#else + redisLog(REDIS_WARNING, + " Dumping of registers not supported for this OS/arch"); +#endif +} + +void sigsegvHandler(int sig, siginfo_t *info, void *secret) { + void *trace[100]; + char **messages = NULL; + int i, trace_size = 0; + ucontext_t *uc = (ucontext_t*) secret; + sds infostring, clients; + struct sigaction act; + REDIS_NOTUSED(info); + + bugReportStart(); + redisLog(REDIS_WARNING, + " Redis %s crashed by signal: %d", REDIS_VERSION, sig); + redisLog(REDIS_WARNING, + " Failed assertion: %s (%s:%d)", server.assert_failed, + server.assert_file, server.assert_line); + + /* Generate the stack trace */ + trace_size = backtrace(trace, 100); + + /* overwrite sigaction with caller's address */ + if (getMcontextEip(uc) != NULL) { + trace[1] = getMcontextEip(uc); + } + messages = backtrace_symbols(trace, trace_size); + redisLog(REDIS_WARNING, "--- STACK TRACE"); + for (i=1; iargc; j++) { + robj *decoded; + + decoded = getDecodedObject(cc->argv[j]); + redisLog(REDIS_WARNING,"argv[%d]: '%s'", j, (char*)decoded->ptr); + decrRefCount(decoded); + } + /* Check if the first argument, usually a key, is found inside the + * selected DB, and if so print info about the associated object. */ + if (cc->argc >= 1) { + robj *val, *key; + dictEntry *de; + + key = getDecodedObject(cc->argv[1]); + de = dictFind(cc->db->dict, key->ptr); + if (de) { + val = dictGetVal(de); + redisLog(REDIS_WARNING,"key '%s' found in DB containing the following object:", key->ptr); + redisLogObjectDebugInfo(val); + } + decrRefCount(key); + } + } + + /* Log dump of processor registers */ + logRegisters(uc); + + redisLog(REDIS_WARNING, +"\n=== REDIS BUG REPORT END. Make sure to include from START to END. ===\n\n" +" Please report the crash opening an issue on github:\n\n" +" http://github.com/antirez/redis/issues\n\n" +); + /* free(messages); Don't call free() with possibly corrupted memory. */ + if (server.daemonize) unlink(server.pidfile); + + /* Make sure we exit with the right signal at the end. So for instance + * the core will be dumped if enabled. */ + sigemptyset (&act.sa_mask); + /* When the SA_SIGINFO flag is set in sa_flags then sa_sigaction + * is used. Otherwise, sa_handler is used */ + act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND; + act.sa_handler = SIG_DFL; + sigaction (sig, &act, NULL); + kill(getpid(),sig); +} +#endif /* HAVE_BACKTRACE */ diff --git a/src/redis.c b/src/redis.c index 6e897d83..3914003d 100644 --- a/src/redis.c +++ b/src/redis.c @@ -31,11 +31,6 @@ #include "slowlog.h" #include "bio.h" -#ifdef HAVE_BACKTRACE -#include -#include -#endif /* HAVE_BACKTRACE */ - #include #include #include @@ -1933,136 +1928,6 @@ void redisAsciiArt(void) { zfree(buf); } -#ifdef HAVE_BACKTRACE -static void *getMcontextEip(ucontext_t *uc) { -#if defined(__FreeBSD__) - return (void*) uc->uc_mcontext.mc_eip; -#elif defined(__dietlibc__) - return (void*) uc->uc_mcontext.eip; -#elif defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_6) - #if __x86_64__ - return (void*) uc->uc_mcontext->__ss.__rip; - #elif __i386__ - return (void*) uc->uc_mcontext->__ss.__eip; - #else - return (void*) uc->uc_mcontext->__ss.__srr0; - #endif -#elif defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_6) - #if defined(_STRUCT_X86_THREAD_STATE64) && !defined(__i386__) - return (void*) uc->uc_mcontext->__ss.__rip; - #else - return (void*) uc->uc_mcontext->__ss.__eip; - #endif -#elif defined(__i386__) - return (void*) uc->uc_mcontext.gregs[14]; /* Linux 32 */ -#elif defined(__X86_64__) || defined(__x86_64__) - return (void*) uc->uc_mcontext.gregs[16]; /* Linux 64 */ -#elif defined(__ia64__) /* Linux IA64 */ - return (void*) uc->uc_mcontext.sc_ip; -#else - return NULL; -#endif -} - -void bugReportStart(void) { - if (server.bug_report_start == 0) { - redisLog(REDIS_WARNING, - "=== REDIS BUG REPORT START: Cut & paste starting from here ==="); - server.bug_report_start = 1; - } -} - -static void sigsegvHandler(int sig, siginfo_t *info, void *secret) { - void *trace[100]; - char **messages = NULL; - int i, trace_size = 0; - ucontext_t *uc = (ucontext_t*) secret; - sds infostring, clients; - struct sigaction act; - REDIS_NOTUSED(info); - - bugReportStart(); - redisLog(REDIS_WARNING, - " Redis %s crashed by signal: %d", REDIS_VERSION, sig); - redisLog(REDIS_WARNING, - " Failed assertion: %s (%s:%d)", server.assert_failed, - server.assert_file, server.assert_line); - - /* Generate the stack trace */ - trace_size = backtrace(trace, 100); - - /* overwrite sigaction with caller's address */ - if (getMcontextEip(uc) != NULL) { - trace[1] = getMcontextEip(uc); - } - messages = backtrace_symbols(trace, trace_size); - redisLog(REDIS_WARNING, "--- STACK TRACE"); - for (i=1; iargc; j++) { - robj *decoded; - - decoded = getDecodedObject(cc->argv[j]); - redisLog(REDIS_WARNING,"argv[%d]: '%s'", j, (char*)decoded->ptr); - decrRefCount(decoded); - } - /* Check if the first argument, usually a key, is found inside the - * selected DB, and if so print info about the associated object. */ - if (cc->argc >= 1) { - robj *val, *key; - dictEntry *de; - - key = getDecodedObject(cc->argv[1]); - de = dictFind(cc->db->dict, key->ptr); - if (de) { - val = dictGetVal(de); - redisLog(REDIS_WARNING,"key '%s' found in DB containing the following object:", key->ptr); - redisLogObjectDebugInfo(val); - } - decrRefCount(key); - } - } - - redisLog(REDIS_WARNING, -"=== REDIS BUG REPORT END. Make sure to include from START to END. ===\n\n" -" Please report the crash opening an issue on github:\n\n" -" http://github.com/antirez/redis/issues\n\n" -); - /* free(messages); Don't call free() with possibly corrupted memory. */ - if (server.daemonize) unlink(server.pidfile); - - /* Make sure we exit with the right signal at the end. So for instance - * the core will be dumped if enabled. */ - sigemptyset (&act.sa_mask); - /* When the SA_SIGINFO flag is set in sa_flags then sa_sigaction - * is used. Otherwise, sa_handler is used */ - act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND; - act.sa_handler = SIG_DFL; - sigaction (sig, &act, NULL); - kill(getpid(),sig); -} -#endif /* HAVE_BACKTRACE */ - static void sigtermHandler(int sig) { REDIS_NOTUSED(sig); diff --git a/src/redis.h b/src/redis.h index 1ac2a2d2..37f0b2ab 100644 --- a/src/redis.h +++ b/src/redis.h @@ -1161,5 +1161,6 @@ void _redisAssert(char *estr, char *file, int line); void _redisPanic(char *msg, char *file, int line); void bugReportStart(void); void redisLogObjectDebugInfo(robj *o); - +void sigsegvHandler(int sig, siginfo_t *info, void *secret); +sds genRedisInfoString(char *section); #endif From eea8c7a4f86785f5b5e325007653ee449d6140cd Mon Sep 17 00:00:00 2001 From: antirez Date: Fri, 20 Jan 2012 12:54:15 +0100 Subject: [PATCH 2/7] added support to dump registers on crash on Linux x64 --- src/debug.c | 29 ++++++++++++++++++++++++++++- src/redis.h | 1 + 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/debug.c b/src/debug.c index 59e15844..bddb082e 100644 --- a/src/debug.c +++ b/src/debug.c @@ -498,7 +498,34 @@ void logRegisters(ucontext_t *uc) { #elif defined(__i386__) return (void*) uc->uc_mcontext.gregs[14]; /* Linux 32 */ #elif defined(__X86_64__) || defined(__x86_64__) - return (void*) uc->uc_mcontext.gregs[16]; /* Linux 64 */ + redisLog(REDIS_WARNING, + "\n" + "RAX:%p RBX:%p RCX:%p RDX:%p\n" + "RDI:%p RSI:%p RBP:%p RSP:%p\n" + "R8:%p R9:%p R10:%p R11:%p\n" + "R12:%p R13:%p R14:%p R15:%p\n" + "RIP:%p EFL:%p CSGSFS:%p", + uc->uc_mcontext.gregs[13], + uc->uc_mcontext.gregs[11], + uc->uc_mcontext.gregs[14], + uc->uc_mcontext.gregs[12], + uc->uc_mcontext.gregs[8], + uc->uc_mcontext.gregs[9], + uc->uc_mcontext.gregs[10], + uc->uc_mcontext.gregs[15], + uc->uc_mcontext.gregs[0], + uc->uc_mcontext.gregs[1], + uc->uc_mcontext.gregs[2], + uc->uc_mcontext.gregs[3], + uc->uc_mcontext.gregs[4], + uc->uc_mcontext.gregs[5], + uc->uc_mcontext.gregs[6], + uc->uc_mcontext.gregs[7], + uc->uc_mcontext.gregs[16], + uc->uc_mcontext.gregs[17], + uc->uc_mcontext.gregs[18] + ); + logStackContent((void**)uc->uc_mcontext.gregs[15]); #else redisLog(REDIS_WARNING, " Dumping of registers not supported for this OS/arch"); diff --git a/src/redis.h b/src/redis.h index 37f0b2ab..8889779a 100644 --- a/src/redis.h +++ b/src/redis.h @@ -20,6 +20,7 @@ #include #include #include +#include #include "ae.h" /* Event driven programming library */ #include "sds.h" /* Dynamic safe strings */ From 632da605831a84fe3d6a17b5d3f4ce7114378f77 Mon Sep 17 00:00:00 2001 From: antirez Date: Fri, 20 Jan 2012 14:37:50 +0100 Subject: [PATCH 3/7] added support to dump registers on crash on Linux x32 --- src/debug.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/debug.c b/src/debug.c index bddb082e..9cfcbdaa 100644 --- a/src/debug.c +++ b/src/debug.c @@ -496,7 +496,30 @@ void logRegisters(ucontext_t *uc) { logStackContent((void**)uc->uc_mcontext->__ss.__esp); #endif #elif defined(__i386__) - return (void*) uc->uc_mcontext.gregs[14]; /* Linux 32 */ + redisLog(REDIS_WARNING, + "\n" + "EAX:%p EBX:%p ECX:%p EDX:%p\n" + "EDI:%p ESI:%p EBP:%p ESP:%p\n" + "SS:%p EFL:%p EIP:%p CS:%p\n" + "DS:%p ES:%p FS:%p GS:%p", + uc->uc_mcontext.gregs[11], + uc->uc_mcontext.gregs[8], + uc->uc_mcontext.gregs[10], + uc->uc_mcontext.gregs[9], + uc->uc_mcontext.gregs[4], + uc->uc_mcontext.gregs[5], + uc->uc_mcontext.gregs[6], + uc->uc_mcontext.gregs[7], + uc->uc_mcontext.gregs[18], + uc->uc_mcontext.gregs[17], + uc->uc_mcontext.gregs[14], + uc->uc_mcontext.gregs[15], + uc->uc_mcontext.gregs[3], + uc->uc_mcontext.gregs[2], + uc->uc_mcontext.gregs[1], + uc->uc_mcontext.gregs[0] + ); + logStackContent((void**)uc->uc_mcontext.gregs[7]); #elif defined(__X86_64__) || defined(__x86_64__) redisLog(REDIS_WARNING, "\n" From 447ebf3bc73016a6137a458bf0314109a0128157 Mon Sep 17 00:00:00 2001 From: antirez Date: Fri, 20 Jan 2012 16:40:43 +0100 Subject: [PATCH 4/7] Better looking registers/stack dump --- src/debug.c | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/src/debug.c b/src/debug.c index 9cfcbdaa..f16bcfd1 100644 --- a/src/debug.c +++ b/src/debug.c @@ -431,7 +431,10 @@ void bugReportStart(void) { void logStackContent(void **sp) { int i; for (i = 15; i >= 0; i--) { - redisLog(REDIS_WARNING, "(%p) -> %p", sp+i, sp[i]); + if (sizeof(long) == 4) + redisLog(REDIS_WARNING, "(%08lx) -> %08lx", sp+i, sp[i]); + else + redisLog(REDIS_WARNING, "(%016lx) -> %016lx", sp+i, sp[i]); } } @@ -441,11 +444,11 @@ void logRegisters(ucontext_t *uc) { #if defined(_STRUCT_X86_THREAD_STATE64) && !defined(__i386__) redisLog(REDIS_WARNING, "\n" - "RAX:%p RBX:%p RCX:%p RDX:%p\n" - "RDI:%p RSI:%p RBP:%p RSP:%p\n" - "R8:%p R9:%p R10:%p R11:%p\n" - "R12:%p R13:%p R14:%p R15:%p\n" - "RIP:%p EFL:%p CS:%p FS:%p GS:%p", + "RAX:%016lx RBX:%016lx\nRCX:%016lx RDX:%016lx\n" + "RDI:%016lx RSI:%016lx\nRBP:%016lx RSP:%016lx\n" + "R8 :%016lx R9 :%016lx\nR10:%016lx R11:%016lx\n" + "R12:%016lx R13:%016lx\nR14:%016lx R15:%016lx\n" + "RIP:%016lx EFL:%016lx\nCS :%016lx FS:%016lx GS:%016lx", uc->uc_mcontext->__ss.__rax, uc->uc_mcontext->__ss.__rbx, uc->uc_mcontext->__ss.__rcx, @@ -472,10 +475,10 @@ void logRegisters(ucontext_t *uc) { #else redisLog(REDIS_WARNING, "\n" - "EAX:%p EBX:%p ECX:%p EDX:%p\n" - "EDI:%p ESI:%p EBP:%p ESP:%p\n" - "SS:%p EFL:%p EIP:%p CS:%p\n" - "DS:%p ES:%p FS:%p GS:%p", + "EAX:%08lx EBX:%08lx ECX:%08lx EDX:%08lx\n" + "EDI:%08lx ESI:%08lx EBP:%08lx ESP:%08lx\n" + "SS:%08lx EFL:%08lx EIP:%08lx CS :%08lx\n" + "DS:%08lx ES:%08lx FS :%08lx GS :%08lx", uc->uc_mcontext->__ss.__eax, uc->uc_mcontext->__ss.__ebx, uc->uc_mcontext->__ss.__ecx, @@ -498,10 +501,10 @@ void logRegisters(ucontext_t *uc) { #elif defined(__i386__) redisLog(REDIS_WARNING, "\n" - "EAX:%p EBX:%p ECX:%p EDX:%p\n" - "EDI:%p ESI:%p EBP:%p ESP:%p\n" - "SS:%p EFL:%p EIP:%p CS:%p\n" - "DS:%p ES:%p FS:%p GS:%p", + "EAX:%08lx EBX:%08lx ECX:%08lx EDX:%08lx\n" + "EDI:%08lx ESI:%08lx EBP:%08lx ESP:%08lx\n" + "SS :%08lx EFL:%08lx EIP:%08lx CS:%08lx\n" + "DS :%08lx ES :%08lx FS :%08lx GS:%08lx", uc->uc_mcontext.gregs[11], uc->uc_mcontext.gregs[8], uc->uc_mcontext.gregs[10], @@ -523,11 +526,11 @@ void logRegisters(ucontext_t *uc) { #elif defined(__X86_64__) || defined(__x86_64__) redisLog(REDIS_WARNING, "\n" - "RAX:%p RBX:%p RCX:%p RDX:%p\n" - "RDI:%p RSI:%p RBP:%p RSP:%p\n" - "R8:%p R9:%p R10:%p R11:%p\n" - "R12:%p R13:%p R14:%p R15:%p\n" - "RIP:%p EFL:%p CSGSFS:%p", + "RAX:%016lx RBX:%016lx\nRCX:%016lx RDX:%016lx\n" + "RDI:%016lx RSI:%016lx\nRBP:%016lx RSP:%016lx\n" + "R8 :%016lx R9 :%016lx\nR10:%016lx R11:%016lx\n" + "R12:%016lx R13:%016lx\nR14:%016lx R15:%016lx\n" + "RIP:%016lx EFL:%016lx\nCSGSFS:%016lx", uc->uc_mcontext.gregs[13], uc->uc_mcontext.gregs[11], uc->uc_mcontext.gregs[14], From a48c8d873bc2a49f66ab398ebed51dc45764ca17 Mon Sep 17 00:00:00 2001 From: antirez Date: Sat, 21 Jan 2012 23:05:32 +0100 Subject: [PATCH 5/7] Fix for hash table collision attack. We simply randomize hash table initialization value at startup time. --- src/debug.c | 2 ++ src/dict.c | 14 ++++++++++++-- src/dict.h | 2 ++ src/redis.c | 8 ++++++-- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/debug.c b/src/debug.c index f16bcfd1..54920032 100644 --- a/src/debug.c +++ b/src/debug.c @@ -589,6 +589,8 @@ void sigsegvHandler(int sig, siginfo_t *info, void *secret) { /* Log INFO and CLIENT LIST */ redisLog(REDIS_WARNING, "--- INFO OUTPUT"); infostring = genRedisInfoString("all"); + infostring = sdscatprintf(infostring, "hash_init_value: %u\n", + dictGetHashFunctionSeed()); redisLogRaw(REDIS_WARNING, infostring); redisLog(REDIS_WARNING, "--- CLIENT LIST OUTPUT"); clients = getAllClientsInfoString(); diff --git a/src/dict.c b/src/dict.c index a573bcd6..a3291375 100644 --- a/src/dict.c +++ b/src/dict.c @@ -85,10 +85,20 @@ unsigned int dictIdentityHashFunction(unsigned int key) return key; } +static int dict_hash_function_seed = 5183; + +void dictSetHashFunctionSeed(unsigned int seed) { + dict_hash_function_seed = seed; +} + +unsigned int dictGetHashFunctionSeed(void) { + return dict_hash_function_seed; +} + /* Generic hash function (a popular one from Bernstein). * I tested a few and this was the best. */ unsigned int dictGenHashFunction(const unsigned char *buf, int len) { - unsigned int hash = 5381; + unsigned int hash = dict_hash_function_seed; while (len--) hash = ((hash << 5) + hash) + (*buf++); /* hash * 33 + c */ @@ -97,7 +107,7 @@ unsigned int dictGenHashFunction(const unsigned char *buf, int len) { /* And a case insensitive version */ unsigned int dictGenCaseHashFunction(const unsigned char *buf, int len) { - unsigned int hash = 5381; + unsigned int hash = dict_hash_function_seed; while (len--) hash = ((hash << 5) + hash) + (tolower(*buf++)); /* hash * 33 + c */ diff --git a/src/dict.h b/src/dict.h index 76451047..5f856953 100644 --- a/src/dict.h +++ b/src/dict.h @@ -162,6 +162,8 @@ void dictEnableResize(void); void dictDisableResize(void); int dictRehash(dict *d, int n); int dictRehashMilliseconds(dict *d, int ms); +void dictSetHashFunctionSeed(unsigned int initval); +unsigned int dictGetHashFunctionSeed(void); /* Hash table types */ extern dictType dictTypeHeapStringCopyKey; diff --git a/src/redis.c b/src/redis.c index 3914003d..7446e72e 100644 --- a/src/redis.c +++ b/src/redis.c @@ -1080,8 +1080,6 @@ void initServer() { scriptingInit(); slowlogInit(); bioInit(); - srand(time(NULL)^getpid()); - } /* Populates the Redis Command Table starting from the hard coded list @@ -1959,9 +1957,15 @@ void setupSignalHandlers(void) { int main(int argc, char **argv) { long long start; + struct timeval tv; + /* We need to initialize our libraries, and the server. */ zmalloc_enable_thread_safeness(); + srand(time(NULL)^getpid()); + gettimeofday(&tv,NULL); + dictSetHashFunctionSeed(tv.tv_sec^tv.tv_usec^getpid()); initServerConfig(); + if (argc >= 2) { int j = 1; /* First option to parse in argv[] */ sds options = sdsempty(); From 06c5523a88ec0f76ff932de5240c8d3ad3b1cc19 Mon Sep 17 00:00:00 2001 From: antirez Date: Sat, 21 Jan 2012 23:34:06 +0100 Subject: [PATCH 6/7] typo in comment fixed --- src/redis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/redis.c b/src/redis.c index 7446e72e..17d7517f 100644 --- a/src/redis.c +++ b/src/redis.c @@ -1959,7 +1959,7 @@ int main(int argc, char **argv) { long long start; struct timeval tv; - /* We need to initialize our libraries, and the server. */ + /* We need to initialize our libraries, and the server configuration. */ zmalloc_enable_thread_safeness(); srand(time(NULL)^getpid()); gettimeofday(&tv,NULL); From b362c111daa0939f86123cb6fb82fbb389cffc7b Mon Sep 17 00:00:00 2001 From: antirez Date: Sun, 22 Jan 2012 01:40:23 +0100 Subject: [PATCH 7/7] fixed typo in hahs function seed default value. It is no longer used but fixed to retain the old constant as default anyway. --- src/dict.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dict.c b/src/dict.c index a3291375..53e16be0 100644 --- a/src/dict.c +++ b/src/dict.c @@ -85,7 +85,7 @@ unsigned int dictIdentityHashFunction(unsigned int key) return key; } -static int dict_hash_function_seed = 5183; +static int dict_hash_function_seed = 5381; void dictSetHashFunctionSeed(unsigned int seed) { dict_hash_function_seed = seed;