In the previous discussions on backtrace support, some people asked for backtraces in more situations. Here is a patch that prints backtraces on SIGABRT, SIGBUS, and SIGSEGV signals. SIGABRT includes assertions and elog(PANIC).

Do signals work like this on Windows? Do we need special EXEC_BACKEND support?

--
Peter Eisentraut              http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
From f790d208dc85a26585a2f5fb3042c29f8b3bbecc Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Wed, 4 Dec 2019 16:34:41 +0100
Subject: [PATCH] Print backtrace on SIGABRT, SIGBUS, SIGSEGV

This removes the backtrace code from the assertion handling, since
that is now also handled by the SIGABRT signal handler.
---
 src/backend/postmaster/postmaster.c | 30 +++++++++++++++++++++++++++++
 src/backend/utils/error/assert.c    | 13 -------------
 2 files changed, 30 insertions(+), 13 deletions(-)

diff --git a/src/backend/postmaster/postmaster.c 
b/src/backend/postmaster/postmaster.c
index 9ff2832c00..fa4dc6772b 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -77,6 +77,10 @@
 #include <netdb.h>
 #include <limits.h>
 
+#ifdef HAVE_EXECINFO_H
+#include <execinfo.h>
+#endif
+
 #ifdef HAVE_SYS_SELECT_H
 #include <sys/select.h>
 #endif
@@ -391,6 +395,7 @@ static void pmdie(SIGNAL_ARGS);
 static void reaper(SIGNAL_ARGS);
 static void sigusr1_handler(SIGNAL_ARGS);
 static void startup_die(SIGNAL_ARGS);
+static void abort_handler(int signum);
 static void dummy_handler(SIGNAL_ARGS);
 static void StartupPacketTimeoutHandler(void);
 static void CleanupBackend(int pid, int exitstatus);
@@ -646,6 +651,9 @@ PostmasterMain(int argc, char *argv[])
        pqsignal_pm(SIGUSR1, sigusr1_handler);  /* message from child process */
        pqsignal_pm(SIGUSR2, dummy_handler);    /* unused, reserve for children 
*/
        pqsignal_pm(SIGCHLD, reaper);   /* handle child termination */
+       pqsignal_pm(SIGABRT, abort_handler);
+       pqsignal_pm(SIGBUS, abort_handler);
+       pqsignal_pm(SIGSEGV, abort_handler);
 
        /*
         * No other place in Postgres should touch SIGTTIN/SIGTTOU handling.  We
@@ -5333,6 +5341,28 @@ startup_die(SIGNAL_ARGS)
        proc_exit(1);
 }
 
+/*
+ * Signal handler for SIGABRT, SIGBUS, SIGSEGV
+ *
+ * If supported, print stack trace, then continue with normal signal handler.
+ */
+static void
+abort_handler(int signum)
+{
+#ifdef HAVE_BACKTRACE_SYMBOLS
+       {
+               void       *buf[100];
+               int                     nframes;
+
+               nframes = backtrace(buf, lengthof(buf));
+               backtrace_symbols_fd(buf, nframes, fileno(stderr));
+       }
+#endif
+
+       pqsignal_pm(signum, SIG_DFL);
+       raise(signum);
+}
+
 /*
  * Dummy signal handler
  *
diff --git a/src/backend/utils/error/assert.c b/src/backend/utils/error/assert.c
index 1069bbee81..2050b4355d 100644
--- a/src/backend/utils/error/assert.c
+++ b/src/backend/utils/error/assert.c
@@ -18,9 +18,6 @@
 #include "postgres.h"
 
 #include <unistd.h>
-#ifdef HAVE_EXECINFO_H
-#include <execinfo.h>
-#endif
 
 /*
  * ExceptionalCondition - Handles the failure of an Assert()
@@ -45,16 +42,6 @@ ExceptionalCondition(const char *conditionName,
        /* Usually this shouldn't be needed, but make sure the msg went out */
        fflush(stderr);
 
-#ifdef HAVE_BACKTRACE_SYMBOLS
-       {
-               void       *buf[100];
-               int                     nframes;
-
-               nframes = backtrace(buf, lengthof(buf));
-               backtrace_symbols_fd(buf, nframes, fileno(stderr));
-       }
-#endif
-
 #ifdef SLEEP_ON_ASSERT
 
        /*
-- 
2.24.0

Reply via email to