-#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
-}
-
-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;
- struct sigaction act;
- REDIS_NOTUSED(info);
-
- redisLog(REDIS_WARNING,
- "======= Ooops! Redis %s got signal: -%d- =======", REDIS_VERSION, sig);
- infostring = genRedisInfoString("all");
- redisLogRaw(REDIS_WARNING, infostring);
- /* It's not safe to sdsfree() the returned string under memory
- * corruption conditions. Let it leak as we are going to abort */
-
- 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);
-
- for (i=1; i<trace_size; ++i)
- redisLog(REDIS_WARNING,"%s", messages[i]);
-
- /* 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);
-
- redisLog(REDIS_WARNING,"Received SIGTERM, scheduling shutdown...");
- server.shutdown_asap = 1;
-}
-
-void setupSignalHandlers(void) {
- struct sigaction act;
-
- /* When the SA_SIGINFO flag is set in sa_flags then sa_sigaction is used.
- * Otherwise, sa_handler is used. */
- sigemptyset(&act.sa_mask);
- act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND;
- act.sa_handler = sigtermHandler;
- sigaction(SIGTERM, &act, NULL);
-
-#ifdef HAVE_BACKTRACE
- sigemptyset(&act.sa_mask);
- act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO;
- act.sa_sigaction = sigsegvHandler;
- sigaction(SIGSEGV, &act, NULL);
- sigaction(SIGBUS, &act, NULL);
- sigaction(SIGFPE, &act, NULL);
- sigaction(SIGILL, &act, NULL);
-#endif
- return;
-}
-