+/*
+ * Do a direct safe exit
+ */
+static void direct_safe_exit(int code)
+{
+ set_signals_handler(on_rescue_exit, sigerr);
+ set_signals_handler(on_rescue_exit, sigterm);
+ exiting = code;
+ exit(code);
+}
+
+/*
+ * Do a safe exit
+ */
+#if WITH_SIG_MONITOR_NO_DEFERRED_EXIT
+# define safe_exit(x) direct_safe_exit(x)
+#else
+#include "jobs.h"
+static void exit_job(int signum, void* arg)
+{
+ exiting = (int)(intptr_t)arg;
+ if (signum)
+ on_rescue_exit(signum);
+ exit(exiting);
+}
+
+static void safe_exit(int code)
+{
+ if (jobs_queue(safe_exit, 0, exit_job, (void*)(intptr_t)code))
+ direct_safe_exit(code);
+}
+#endif
+
+#if !WITH_SIG_MONITOR_DUMPSTACK
+
+static inline void safe_dumpstack(int crop, int signum) {}
+#define in_safe_dumpstack (0)
+
+#else
+
+static _Thread_local int in_safe_dumpstack;
+
+static void safe_dumpstack_cb(int signum, void *closure)
+{
+ int *args = closure;
+ if (signum)
+ ERROR("Can't provide backtrace: raised signal %s", strsignal(signum));
+ else
+ dumpstack(args[0], args[1]);
+}
+
+static void safe_dumpstack(int crop, int signum)
+{
+ int args[2] = { crop + 3, signum };
+
+ in_safe_dumpstack = 1;
+ sig_monitor(0, safe_dumpstack_cb, args);
+ in_safe_dumpstack = 0;
+}
+#endif
+
+/* Handles signals that terminate the process */
+static void on_signal_terminate (int signum)
+{
+ if (!in_safe_dumpstack) {
+ ERROR("Terminating signal %d received: %s", signum, strsignal(signum));
+ if (signum == SIGABRT)
+ safe_dumpstack(3, signum);
+ }
+ safe_exit(1);
+}
+
+/* Handles monitored signals that can be continued */
+static void on_signal_error(int signum)
+{
+ if (!in_safe_dumpstack) {
+ ERROR("ALERT! signal %d received: %s", signum, strsignal(signum));
+
+ safe_dumpstack(3, signum);
+ }
+ monitor_raise(signum);
+
+ if (signum != SIG_FOR_TIMER) {
+ ERROR("Unmonitored signal %d received: %s", signum, strsignal(signum));
+ safe_exit(2);
+ }
+}
+
+/*
+static void disable_signal_handling()
+{
+ set_signals_handler(SIG_DFL, sigerr);
+ set_signals_handler(SIG_DFL, sigterm);
+ enabled = 0;
+}
+*/
+
+static int enable_signal_handling()
+{
+ if (!set_signals_handler(on_signal_error, sigerr)
+ || !set_signals_handler(on_signal_terminate, sigterm)) {
+ return -1;
+ }
+ enabled = 1;
+ return 0;
+}
+#endif
+/******************************************************************************/
+
+int sig_monitor_init(int enable)
+{
+ return enable ? enable_signal_handling() : 0;