Fedora 30 packaging fix issu
[src/app-framework-binder.git] / src / sig-monitor.c
index 7598250..9e13fa1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 "IoT.bzh"
+ * Copyright (C) 2017, 2018 "IoT.bzh"
  * Author José Bollo <jose.bollo@iot.bzh>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -40,6 +40,12 @@ static _Thread_local int in_safe_dumpstack;
 static _Thread_local int thread_timer_set;
 static _Thread_local timer_t thread_timerid;
 
+/* internal signal lists */
+static int sigerr[] = { SIG_FOR_TIMER, SIGSEGV, SIGFPE, SIGILL, SIGBUS, 0 };
+static int sigterm[] = { SIGINT, SIGABRT, SIGTERM, 0 };
+static int exiting = 0;
+static int enabled = 0;
+
 /*
  * Dumps the current stack
  */
@@ -87,7 +93,7 @@ static void safe_dumpstack_cb(int signum, void *closure)
 
 static void safe_dumpstack(int crop, int signum)
 {
-       int args[2] = { crop, signum };
+       int args[2] = { crop + 3, signum };
 
        in_safe_dumpstack = 1;
        sig_monitor(0, safe_dumpstack_cb, args);
@@ -161,6 +167,44 @@ static inline void timeout_delete()
        }
 }
 
+/* install the handlers */
+static int install(void (*handler)(int), int *signals)
+{
+       int result = 1;
+       struct sigaction sa;
+
+       sa.sa_handler = handler;
+       sigemptyset(&sa.sa_mask);
+       sa.sa_flags = SA_NODEFER;
+       while(*signals > 0) {
+               if (sigaction(*signals, &sa, NULL) < 0) {
+                       ERROR("failed to install signal handler for signal %s: %m", strsignal(*signals));
+                       result = 0;
+               }
+               signals++;
+       }
+       return result;
+}
+
+/*
+ * rescue exit
+ */
+static void on_rescue_exit(int signum)
+{
+       ERROR("Rescue exit for signal %d: %s", signum, strsignal(signum));
+       _exit(exiting);
+}
+
+/*
+ * Do a safe exit
+ */
+static void safe_exit(int code)
+{
+       install(on_rescue_exit, sigerr);
+       install(on_rescue_exit, sigterm);
+       exiting = code;
+       exit(code);
+}
 
 /* Handles signals that terminate the process */
 static void on_signal_terminate (int signum)
@@ -170,14 +214,12 @@ static void on_signal_terminate (int signum)
                if (signum == SIGABRT)
                        safe_dumpstack(3, signum);
        }
-       exit(1);
+       safe_exit(1);
 }
 
 /* Handles monitored signals that can be continued */
 static void on_signal_error(int signum)
 {
-       sigset_t sigset;
-
        if (in_safe_dumpstack)
                longjmp(*error_handler, signum);
 
@@ -192,34 +234,28 @@ static void on_signal_error(int signum)
                longjmp(*error_handler, signum);
 
        ERROR("Unmonitored signal %d received: %s", signum, strsignal(signum));
-       exit(2);
+       safe_exit(2);
 }
 
-/* install the handlers */
-static int install(void (*handler)(int), int *signals)
+void sig_monitor_disable()
 {
-       int result = 1;
-       struct sigaction sa;
-
-       sa.sa_handler = handler;
-       sigemptyset(&sa.sa_mask);
-       sa.sa_flags = SA_NODEFER;
-       while(*signals > 0) {
-               if (sigaction(*signals, &sa, NULL) < 0) {
-                       ERROR("failed to install signal handler for signal %s: %m", strsignal(*signals));
-                       result = 0;
-               }
-               signals++;
-       }
-       return result;
+       enabled = 0;
+       install(SIG_DFL, sigerr);
+       install(SIG_DFL, sigterm);
 }
 
-int sig_monitor_init()
+int sig_monitor_enable()
 {
-       static int sigerr[] = { SIG_FOR_TIMER, SIGSEGV, SIGFPE, SIGILL, SIGBUS, 0 };
-       static int sigterm[] = { SIGINT, SIGABRT, SIGTERM, 0 };
+       enabled = install(on_signal_error, sigerr) && install(on_signal_terminate, sigterm);
+       if (enabled)
+               return 0;
+       sig_monitor_disable();
+       return -1;
+}
 
-       return (install(on_signal_error, sigerr) & install(on_signal_terminate, sigterm)) - 1;
+int sig_monitor_init(int enable)
+{
+       return enable ? sig_monitor_enable() : (sig_monitor_disable(), 0);
 }
 
 int sig_monitor_init_timeouts()
@@ -232,7 +268,7 @@ void sig_monitor_clean_timeouts()
        timeout_delete();
 }
 
-void sig_monitor(int timeout, void (*function)(int sig, void*), void *arg)
+static void monitor(int timeout, void (*function)(int sig, void*), void *arg)
 {
        volatile int signum, signum2;
        sigjmp_buf jmpbuf, *older;
@@ -241,17 +277,30 @@ void sig_monitor(int timeout, void (*function)(int sig, void*), void *arg)
        signum = setjmp(jmpbuf);
        if (signum == 0) {
                error_handler = &jmpbuf;
-               if (timeout)
+               if (timeout) {
+                       timeout_create();
                        timeout_arm(timeout);
+               }
                function(0, arg);
        } else {
                signum2 = setjmp(jmpbuf);
                if (signum2 == 0)
                        function(signum, arg);
        }
-       error_handler = older;
        if (timeout)
                timeout_disarm();
+       error_handler = older;
 }
 
+void sig_monitor(int timeout, void (*function)(int sig, void*), void *arg)
+{
+       if (enabled)
+               monitor(timeout, function, arg);
+       else
+               function(0, arg);
+}
 
+void sig_monitor_dumpstack()
+{
+       return dumpstack(1, 0);
+}