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