diff options
author | José Bollo <jose.bollo@iot.bzh> | 2018-08-28 17:15:12 +0200 |
---|---|---|
committer | José Bollo <jose.bollo@iot.bzh> | 2018-08-28 17:35:24 +0200 |
commit | a02a1627a954432cc65ec981cada8ba420d7ad2f (patch) | |
tree | 3111ce06668dc15d23b26500934ba5bf65341771 | |
parent | 5dd7df31306b95a3fafe6d3238d4553107a6c70f (diff) |
Allow choice to trap or not program faults
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>
-rw-r--r-- | src/afb-config.c | 59 | ||||
-rw-r--r-- | src/jobs.c | 13 | ||||
-rw-r--r-- | src/main-afb-daemon.c | 26 | ||||
-rw-r--r-- | src/sig-monitor.c | 37 | ||||
-rw-r--r-- | src/sig-monitor.h | 4 |
5 files changed, 110 insertions, 29 deletions
diff --git a/src/afb-config.c b/src/afb-config.c index 38dd9b71..669bbc57 100644 --- a/src/afb-config.c +++ b/src/afb-config.c @@ -108,12 +108,13 @@ #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) @@ -49,13 +49,6 @@ #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; diff --git a/src/main-afb-daemon.c b/src/main-afb-daemon.c index 0db84bc1..06aeb58d 100644 --- a/src/main-afb-daemon.c +++ b/src/main-afb-daemon.c @@ -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" @@ -59,12 +58,15 @@ #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"); diff --git a/src/sig-monitor.c b/src/sig-monitor.c index e15c32de..15fe260d 100644 --- a/src/sig-monitor.c +++ b/src/sig-monitor.c @@ -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); +} diff --git a/src/sig-monitor.h b/src/sig-monitor.h index 9121ac8f..5fdac167 100644 --- a/src/sig-monitor.h +++ b/src/sig-monitor.h @@ -17,9 +17,11 @@ #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); |