summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/log.c11
-rw-r--r--lib/sigevent.c17
2 files changed, 28 insertions, 0 deletions
diff --git a/lib/log.c b/lib/log.c
index 69225dbf7..66320230c 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -734,6 +734,17 @@ openzlog (const char *progname, const char *protoname, u_short instance,
openlog (progname, syslog_flags, zl->facility);
zlog_default = zl;
+
+#ifdef HAVE_GLIBC_BACKTRACE
+ /* work around backtrace() using lazily resolved dynamically linked
+ * symbols, which will otherwise cause funny breakage in the SEGV handler.
+ * (particularly, the dynamic linker can call malloc(), which uses locks
+ * in programs linked with -pthread, thus can deadlock.) */
+ void *bt[4];
+ backtrace (bt, array_size(bt));
+ free (backtrace_symbols (bt, 0));
+ backtrace_symbols_fd (bt, 0, 0);
+#endif
}
void
diff --git a/lib/sigevent.c b/lib/sigevent.c
index 09f07180c..b2059a17b 100644
--- a/lib/sigevent.c
+++ b/lib/sigevent.c
@@ -233,6 +233,18 @@ core_handler(int signo
#endif
)
{
+ /* make sure we don't hang in here. default for SIGALRM is terminate.
+ * - if we're in backtrace for more than a second, abort. */
+ struct sigaction sa_default = { .sa_handler = SIG_DFL };
+ sigaction (SIGALRM, &sa_default, NULL);
+
+ sigset_t sigset;
+ sigemptyset (&sigset);
+ sigaddset (&sigset, SIGALRM);
+ sigprocmask (SIG_UNBLOCK, &sigset, NULL);
+
+ alarm (1);
+
zlog_signal(signo, "aborting..."
#ifdef SA_SIGINFO
, siginfo, program_counter(context)
@@ -327,6 +339,11 @@ trap_default_signals(void)
act.sa_handler = sigmap[i].handler;
act.sa_flags = 0;
#endif
+#ifdef SA_RESETHAND
+ /* don't try to print backtraces recursively */
+ if (sigmap[i].handler == core_handler)
+ act.sa_flags |= SA_RESETHAND;
+#endif
}
if (sigaction(sigmap[i].sigs[j],&act,NULL) < 0)
zlog_warn("Unable to set signal handler for signal %d: %s",