Allow choice to trap or not program faults 89/16389/1
authorJosé Bollo <jose.bollo@iot.bzh>
Tue, 28 Aug 2018 15:15:12 +0000 (17:15 +0200)
committerJosé Bollo <jose.bollo@iot.bzh>
Tue, 28 Aug 2018 15:35:24 +0000 (17:35 +0200)
The binder traps faults by default to recover as much as
possible from unexpected errors.

Developers may need to remove that behaviour to get core file.

This introduces 2 ways to set or remove the trapping of faults:

 - the environment variable AFB_TRAP_FAULTS

 - the command line option --trap-faults

Both take a boolean value set using on of the following words:

 1  yes  true   on    -- enable trapping of faults (the default)
 0  no   false  off   -- disable trapping of faults

Bug-AGL: SPEC-1702

Change-Id: I6c6a3b933dbda9922a6079c390a601c533d49e55
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
src/afb-config.c
src/jobs.c
src/main-afb-daemon.c
src/sig-monitor.c
src/sig-monitor.h

index 38dd9b7..669bbc5 100644 (file)
 #define SET_TRACESVC        26
 #endif
 
+#define SET_TRAP_FAULTS      27
+
 #if defined(WITH_DBUS_TRANSPARENCY)
 #   define ADD_DBUS_CLIENT  30
 #   define ADD_DBUS_SERVICE 31
 #endif
 
-
 #define ADD_AUTO_API       'A'
 #define ADD_BINDING        'b'
 #define SET_CONFIG         'C'
@@ -220,6 +221,8 @@ static struct option_desc optdefs[] = {
        {ADD_SET,             1, "set",         "Set parameters ([API]/[KEY]:JSON or {\"API\":{\"KEY\":JSON}}" },
        {SET_OUTPUT,          1, "output",      "Redirect stdout and stderr to output file (when --daemon)"},
 
+       {SET_TRAP_FAULTS,     1, "trap-faults", "Trap faults: on, off, yes, no, true, false, 1, 0 (default: true)"},
+
        {0, 0, NULL, NULL}
 /* *INDENT-ON* */
 };
@@ -453,6 +456,29 @@ static struct json_object *to_jbool(int value)
 * arguments helpers
 ***********************************/
 
+static int string_to_bool(const char *value)
+{
+       static const char true_names[] = "1\0yes\0true\0on";
+       static const char false_names[] = "0\0no\0false\0off";
+       size_t pos;
+
+       pos = 0;
+       while (pos < sizeof true_names)
+               if (strcasecmp(value, &true_names[pos]))
+                       pos += 1 + strlen(&true_names[pos]);
+               else
+                       return 1;
+
+       pos = 0;
+       while (pos < sizeof false_names)
+               if (strcasecmp(value, &false_names[pos]))
+                       pos += 1 + strlen(&false_names[pos]);
+               else
+                       return 0;
+
+       return -1;
+}
+
 static void noarg(int optid)
 {
        if (optarg) {
@@ -471,6 +497,17 @@ static const char *get_arg(int optid)
        return optarg;
 }
 
+static int get_arg_bool(int optid)
+{
+       int value = string_to_bool(get_arg(optid));
+       if (value < 0) {
+               ERROR("option [--%s] needs a boolean value: yes/no, true/false, on/off, 1/0",
+                               name_of_optid(optid));
+               exit(1);
+       }
+       return value;
+}
+
 static void config_del(struct json_object *config, int optid)
 {
        return json_object_object_del(config, name_of_optid(optid));
@@ -789,6 +826,11 @@ static void parse_arguments_inner(int argc, char **argv, struct json_object *con
                        config_set_bool(config, SET_DAEMON, optid != SET_FOREGROUND);
                        break;
 
+               case SET_TRAP_FAULTS:
+                       config_set_bool(config, optid, get_arg_bool(optid));
+                       break;
+
+
                case SET_TRACEREQ:
                        config_set_optenum(config, optid, afb_hook_flags_xreq_from_text);
                        break;
@@ -941,6 +983,20 @@ static void on_environment_enum(struct json_object *config, int optid, const cha
        }
 }
 
+static void on_environment_bool(struct json_object *config, int optid, const char *name)
+{
+       char *value = getenv(name);
+       int asbool;
+
+       if (value) {
+               asbool = string_to_bool(value);
+               if (asbool < 0)
+                       WARNING("Unknown value %s for environment variable %s, ignored", value, name);
+               else
+                       config_set_bool(config, optid, asbool);
+       }
+}
+
 static void parse_environment(struct json_object *config)
 {
        on_environment_enum(config, SET_TRACEREQ, "AFB_TRACEREQ", afb_hook_flags_xreq_from_text);
@@ -954,6 +1010,7 @@ static void parse_environment(struct json_object *config)
        on_environment_enum(config, SET_TRACEDITF, "AFB_TRACEDITF", afb_hook_flags_legacy_ditf_from_text);
        on_environment_enum(config, SET_TRACESVC, "AFB_TRACESVC", afb_hook_flags_legacy_svc_from_text);
 #endif
+       on_environment_bool(config, SET_TRAP_FAULTS, "AFB_TRAP_FAULTS");
 }
 
 struct json_object *afb_config_parse_arguments(int argc, char **argv)
index 27b7dfb..a6357c8 100644 (file)
 #include "fdev-epoll.h"
 #endif
 
-#if 0
-#define _alert_ "do you really want to remove signal monitoring?"
-#define sig_monitor_init_timeouts()  ((void)0)
-#define sig_monitor_clean_timeouts() ((void)0)
-#define sig_monitor(to,cb,arg)       (cb(0,arg))
-#endif
-
 #define EVENT_TIMEOUT_TOP      ((uint64_t)-1)
 #define EVENT_TIMEOUT_CHILD    ((uint64_t)10000)
 
@@ -875,12 +868,6 @@ int jobs_start(int allowed_count, int start_count, int waiter_count, void (*star
                goto error;
        }
 
-       /* start */
-       if (sig_monitor_init() < 0) {
-               ERROR("failed to initialise signal handlers");
-               goto error;
-       }
-
        /* records the allowed count */
        allowed = allowed_count;
        started = 0;
index 0db84bc..06aeb58 100644 (file)
@@ -50,7 +50,6 @@
 #include "afb-hsrv.h"
 #include "afb-hreq.h"
 #include "afb-xreq.h"
-#include "jobs.h"
 #include "afb-session.h"
 #include "verbose.h"
 #include "afb-common.h"
 #include "afb-hook.h"
 #include "afb-hook-flags.h"
 #include "afb-debug.h"
-#include "process-name.h"
-#include "wrap-json.h"
 #if defined(WITH_SUPERVISION)
 #   include "afb-supervision.h"
 #endif
 
+#include "process-name.h"
+#include "wrap-json.h"
+#include "jobs.h"
+#include "sig-monitor.h"
+
 /*
    if SELF_PGROUP == 0 the launched command is the group leader
    if SELF_PGROUP != 0 afb-daemon is the group leader
@@ -823,15 +825,23 @@ error:
 
 int main(int argc, char *argv[])
 {
-       struct json_object *name;
+       struct json_object *obj;
        afb_debug("main-entry");
 
        // ------------- Build session handler & init config -------
        main_config = afb_config_parse_arguments(argc, argv);
-       if (json_object_object_get_ex(main_config, "name", &name)) {
-               verbose_set_name(json_object_get_string(name), 0);
-               process_name_set_name(json_object_get_string(name));
-               process_name_replace_cmdline(argv, json_object_get_string(name));
+       if (sig_monitor_init(
+               !json_object_object_get_ex(main_config, "trap-faults", &obj)
+                       || json_object_get_boolean(obj)) < 0) {
+               ERROR("failed to initialise signal handlers");
+               return 1;
+       }
+
+
+       if (json_object_object_get_ex(main_config, "name", &obj)) {
+               verbose_set_name(json_object_get_string(obj), 0);
+               process_name_set_name(json_object_get_string(obj));
+               process_name_replace_cmdline(argv, json_object_get_string(obj));
        }
        afb_debug("main-args");
 
index e15c32d..15fe260 100644 (file)
@@ -44,6 +44,7 @@ static _Thread_local timer_t thread_timerid;
 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
@@ -236,9 +237,25 @@ static void on_signal_error(int signum)
        safe_exit(2);
 }
 
-int sig_monitor_init()
+void sig_monitor_disable()
 {
-       return (install(on_signal_error, sigerr) & install(on_signal_terminate, sigterm)) - 1;
+       enabled = 0;
+       install(SIG_DFL, sigerr);
+       install(SIG_DFL, sigterm);
+}
+
+int sig_monitor_enable()
+{
+       enabled = install(on_signal_error, sigerr) && install(on_signal_terminate, sigterm);
+       if (enabled)
+               return 0;
+       sig_monitor_disable();
+       return -1;
+}
+
+int sig_monitor_init(int enable)
+{
+       return enable ? sig_monitor_enable() : (sig_monitor_disable(), 0);
 }
 
 int sig_monitor_init_timeouts()
@@ -251,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;
@@ -260,17 +277,25 @@ 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);
+}
index 9121ac8..5fdac16 100644 (file)
 
 #pragma once
 
-extern int sig_monitor_init();
+extern int sig_monitor_init(int enable);
 extern void sig_monitor_clean_timeouts();
 extern int sig_monitor_init_timeouts();
+extern void sig_monitor_disable();
+extern int sig_monitor_enable();
 
 extern void sig_monitor(int timeout, void (*function)(int sig, void*), void *arg);