]> git.saurik.com Git - redis.git/commitdiff
all the stack trace related functions are now in debug.c. Now Redis dumps registers...
authorantirez <antirez@gmail.com>
Fri, 20 Jan 2012 11:20:45 +0000 (12:20 +0100)
committerantirez <antirez@gmail.com>
Fri, 20 Jan 2012 11:20:45 +0000 (12:20 +0100)
src/debug.c
src/redis.c
src/redis.h

index 728aa8a18cc052277f8520759d4cb916e845267e..59e15844ca7cf7fbecfd3e03132a75a4aeca5079 100644 (file)
@@ -2,6 +2,12 @@
 #include "sha1.h"   /* SHA1 is used for DEBUG DIGEST */
 
 #include <arpa/inet.h>
+#include <signal.h>
+
+#ifdef HAVE_BACKTRACE
+#include <execinfo.h>
+#include <ucontext.h>
+#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; i<trace_size; ++i)
+        redisLog(REDIS_WARNING,"%s", messages[i]);
+
+    /* Log INFO and CLIENT LIST */
+    redisLog(REDIS_WARNING, "--- INFO OUTPUT");
+    infostring = genRedisInfoString("all");
+    redisLogRaw(REDIS_WARNING, infostring);
+    redisLog(REDIS_WARNING, "--- CLIENT LIST OUTPUT");
+    clients = getAllClientsInfoString();
+    redisLogRaw(REDIS_WARNING, clients);
+    /* Don't sdsfree() strings to avoid a crash. Memory may be corrupted. */
+
+    /* Log CURRENT CLIENT info */
+    if (server.current_client) {
+        redisClient *cc = server.current_client;
+        sds client;
+        int j;
+
+        redisLog(REDIS_WARNING, "--- CURRENT CLIENT INFO");
+        client = getClientInfoString(cc);
+        redisLog(REDIS_WARNING,"client: %s", client);
+        /* Missing sdsfree(client) to avoid crash if memory is corrupted. */
+        for (j = 0; j < cc->argc; 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 */
index 6e897d83c0ecf2c7dbbc4df45a69ddbf9df3b00c..3914003d04b3b0c5987a82c9e8e2f155101bbbd9 100644 (file)
 #include "slowlog.h"
 #include "bio.h"
 
-#ifdef HAVE_BACKTRACE
-#include <execinfo.h>
-#include <ucontext.h>
-#endif /* HAVE_BACKTRACE */
-
 #include <time.h>
 #include <signal.h>
 #include <sys/wait.h>
@@ -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; i<trace_size; ++i)
-        redisLog(REDIS_WARNING,"%s", messages[i]);
-
-    /* Log INFO and CLIENT LIST */
-    redisLog(REDIS_WARNING, "--- INFO OUTPUT");
-    infostring = genRedisInfoString("all");
-    redisLogRaw(REDIS_WARNING, infostring);
-    redisLog(REDIS_WARNING, "--- CLIENT LIST OUTPUT");
-    clients = getAllClientsInfoString();
-    redisLogRaw(REDIS_WARNING, clients);
-    /* Don't sdsfree() strings to avoid a crash. Memory may be corrupted. */
-
-    /* Log CURRENT CLIENT info */
-    if (server.current_client) {
-        redisClient *cc = server.current_client;
-        sds client;
-        int j;
-
-        redisLog(REDIS_WARNING, "--- CURRENT CLIENT INFO");
-        client = getClientInfoString(cc);
-        redisLog(REDIS_WARNING,"client: %s", client);
-        /* Missing sdsfree(client) to avoid crash if memory is corrupted. */
-        for (j = 0; j < cc->argc; 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);
 
index 1ac2a2d287b7d74222a62520074e4a1d66c29327..37f0b2ab8fc18b547fe0a0b3e6f3b8516c3f4f9c 100644 (file)
@@ -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