diff options
author | antirez <antirez@gmail.com> | 2011-11-24 15:47:26 +0100 |
---|---|---|
committer | antirez <antirez@gmail.com> | 2011-11-24 15:53:35 +0100 |
commit | 8a82ee0f3c97554f0a0d0f525df223da3b796aad (patch) | |
tree | a9d92f2a4fd716beb1fcf8577955a01e3dc31312 | |
parent | f4e2abfcd490771c66f9c6bc2b47b7c20ff82a8c (diff) | |
download | redis-8a82ee0f3c97554f0a0d0f525df223da3b796aad.tar.gz |
better bug report info on crash (backported from unstable)
-rw-r--r-- | src/debug.c | 7 | ||||
-rw-r--r-- | src/redis.c | 44 | ||||
-rw-r--r-- | src/redis.h | 6 |
3 files changed, 49 insertions, 8 deletions
diff --git a/src/debug.c b/src/debug.c index b937cd3b0..3d20cddd8 100644 --- a/src/debug.c +++ b/src/debug.c @@ -337,15 +337,20 @@ void debugCommand(redisClient *c) { } void _redisAssert(char *estr, char *file, int line) { + bugReportStart(); redisLog(REDIS_WARNING,"=== ASSERTION FAILED ==="); redisLog(REDIS_WARNING,"==> %s:%d '%s' is not true",file,line,estr); #ifdef HAVE_BACKTRACE - redisLog(REDIS_WARNING,"(forcing SIGSEGV in order to print the stack trace)"); + server.assert_failed = estr; + server.assert_file = file; + server.assert_line = line; + redisLog(REDIS_WARNING,"(forcing SIGSEGV to print the bug report.)"); *((char*)-1) = 'x'; #endif } void _redisPanic(char *msg, char *file, int line) { + bugReportStart(); redisLog(REDIS_WARNING,"!!! Software Failure. Press left mouse button to continue"); redisLog(REDIS_WARNING,"Guru Meditation: %s #%s:%d",msg,file,line); #ifdef HAVE_BACKTRACE diff --git a/src/redis.c b/src/redis.c index 95eb57baf..903354e35 100644 --- a/src/redis.c +++ b/src/redis.c @@ -886,6 +886,12 @@ void initServerConfig() { /* Slow log */ server.slowlog_log_slower_than = REDIS_SLOWLOG_LOG_SLOWER_THAN; server.slowlog_max_len = REDIS_SLOWLOG_MAX_LEN; + + /* Assert */ + server.assert_failed = "<no assertion failed>"; + server.assert_file = "<no file>"; + server.assert_line = 0; + server.bug_report_start = 0; } void initServer() { @@ -1703,32 +1709,56 @@ static void *getMcontextEip(ucontext_t *uc) { #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; + sds infostring, clients; struct sigaction act; REDIS_NOTUSED(info); + bugReportStart(); redisLog(REDIS_WARNING, - "======= Ooops! Redis %s got signal: -%d- =======", REDIS_VERSION, sig); - infostring = genRedisInfoString(); - redisLog(REDIS_WARNING, "%s",infostring); - /* It's not safe to sdsfree() the returned string under memory - * corruption conditions. Let it leak as we are going to abort */ + " 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; i<trace_size; ++i) redisLog(REDIS_WARNING,"%s", messages[i]); + /* Log INFO and CLIENT LIST */ + redisLog(REDIS_WARNING, "--- INFO OUTPUT"); + infostring = genRedisInfoString(); + redisLog(REDIS_WARNING, infostring); + redisLog(REDIS_WARNING, "--- CLIENT LIST OUTPUT"); + clients = getAllClientsInfoString(); + redisLog(REDIS_WARNING, clients); + /* Don't sdsfree() strings to avoid a crash. Memory may be corrupted. */ + + 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); diff --git a/src/redis.h b/src/redis.h index aff39fc77..6090860d6 100644 --- a/src/redis.h +++ b/src/redis.h @@ -236,6 +236,7 @@ #define redisPanic(_e) _redisPanic(#_e,__FILE__,__LINE__),_exit(1) void _redisAssert(char *estr, char *file, int line); void _redisPanic(char *msg, char *file, int line); +void bugReportStart(void); /*----------------------------------------------------------------------------- * Data types @@ -534,6 +535,11 @@ struct redisServer { /* Misc */ unsigned lruclock:22; /* clock incrementing every minute, for LRU */ unsigned lruclock_padding:10; + /* Assert & bug reportign */ + char *assert_failed; + char *assert_file; + int assert_line; + int bug_report_start; /* True if bug report header already logged. */ }; typedef struct pubsubPattern { |