From a02a1627a954432cc65ec981cada8ba420d7ad2f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Bollo?= Date: Tue, 28 Aug 2018 17:15:12 +0200 Subject: [PATCH] Allow choice to trap or not program faults MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 --- src/afb-config.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/jobs.c | 13 ------------ src/main-afb-daemon.c | 26 ++++++++++++++++------- src/sig-monitor.c | 37 ++++++++++++++++++++++++++------ 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) diff --git a/src/jobs.c b/src/jobs.c index 27b7dfbf..a6357c87 100644 --- a/src/jobs.c +++ b/src/jobs.c @@ -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); -- 2.16.6