From ceaffc8d0da402cf8bc689bb8304a175f39e30bd Mon Sep 17 00:00:00 2001 From: "Meir Shpilraien (Spielrein)" Date: Tue, 3 Nov 2020 14:59:21 +0200 Subject: [PATCH] Added crash report on SIGABRT (#8004) The reason that we want to get a full crash report on SIGABRT is that the jmalloc, when detecting a corruption, calls abort(). This will cause the Redis to exist silently without any report and without any way to analyze what happened. --- src/debug.c | 6 ++++++ src/redis-check-rdb.c | 1 + src/server.c | 2 ++ tests/integration/logging.tcl | 11 +++++++++++ 4 files changed, 20 insertions(+) diff --git a/src/debug.c b/src/debug.c index d1a30ae1b..e21440f84 100644 --- a/src/debug.c +++ b/src/debug.c @@ -839,6 +839,9 @@ void _serverAssert(const char *estr, const char *file, int line) { #endif printCrashReport(); } + + // remove the signal handler so on abort() we will output the crash report. + removeSignalHandlers(); bugReportEnd(0, 0); } @@ -923,6 +926,9 @@ void _serverPanic(const char *file, int line, const char *msg, ...) { #endif printCrashReport(); } + + // remove the signal handler so on abort() we will output the crash report. + removeSignalHandlers(); bugReportEnd(0, 0); } diff --git a/src/redis-check-rdb.c b/src/redis-check-rdb.c index a9d110aa8..f399864dd 100644 --- a/src/redis-check-rdb.c +++ b/src/redis-check-rdb.c @@ -172,6 +172,7 @@ void rdbCheckSetupSignals(void) { sigaction(SIGBUS, &act, NULL); sigaction(SIGFPE, &act, NULL); sigaction(SIGILL, &act, NULL); + sigaction(SIGABRT, &act, NULL); } /* Check the specified RDB file. Return 0 if the RDB looks sane, otherwise diff --git a/src/server.c b/src/server.c index cd45dd837..f57bf01a7 100644 --- a/src/server.c +++ b/src/server.c @@ -5004,6 +5004,7 @@ void setupSignalHandlers(void) { sigaction(SIGBUS, &act, NULL); sigaction(SIGFPE, &act, NULL); sigaction(SIGILL, &act, NULL); + sigaction(SIGABRT, &act, NULL); } return; } @@ -5017,6 +5018,7 @@ void removeSignalHandlers(void) { sigaction(SIGBUS, &act, NULL); sigaction(SIGFPE, &act, NULL); sigaction(SIGILL, &act, NULL); + sigaction(SIGABRT, &act, NULL); } /* This is the signal handler for children process. It is currently useful diff --git a/tests/integration/logging.tcl b/tests/integration/logging.tcl index c1f4854d4..3314f0f1d 100644 --- a/tests/integration/logging.tcl +++ b/tests/integration/logging.tcl @@ -22,3 +22,14 @@ if {$system_name eq {linux} || $system_name eq {darwin}} { } } } + +set server_path [tmpdir server1.log] +start_server [list overrides [list dir $server_path]] { + test "Crash report generated on SIGABRT" { + set pid [s process_id] + exec kill -SIGABRT $pid + set pattern "*STACK TRACE*" + set result [exec tail -1000 < [srv 0 stdout]] + assert {[string match $pattern $result]} + } +}