X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fmain-afb-daemon.c;h=3421be819c5fbd3f789c3a7d0a5e0e82be3e3ef8;hb=6f13ad1989875b5a0ce50b24211fd1fba093735f;hp=df0efbcc77f919c50c46d65c05f1e34ec2b9f883;hpb=e39610f8c9b2e6bbb8a460f7d7ccccbc5161b4ed;p=src%2Fapp-framework-binder.git diff --git a/src/main-afb-daemon.c b/src/main-afb-daemon.c index df0efbcc..3421be81 100644 --- a/src/main-afb-daemon.c +++ b/src/main-afb-daemon.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2018 "IoT.bzh" + * Copyright (C) 2015-2019 "IoT.bzh" * Author "Fulup Ar Foll" * Author José Bollo * @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include #include @@ -36,30 +38,40 @@ #include -#include "afb-config.h" +#include "afb-args.h" #include "afb-hswitch.h" #include "afb-apiset.h" #include "afb-autoset.h" #include "afb-api-so.h" -#if defined(WITH_DBUS_TRANSPARENCY) +#if WITH_DBUS_TRANSPARENCY # include "afb-api-dbus.h" #endif #include "afb-api-ws.h" #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-export.h" #include "afb-monitor.h" +#if WITH_AFB_HOOK #include "afb-hook.h" #include "afb-hook-flags.h" +#endif #include "afb-debug.h" +#if WITH_SUPERVISION +# include "afb-supervision.h" +#endif + #include "process-name.h" #include "wrap-json.h" -#if defined(WITH_SUPERVISION) -# include "afb-supervision.h" +#include "jobs.h" +#include "sig-monitor.h" +#include "watchdog.h" + +#if !defined(DEFAULT_BINDER_INTERFACE) +# define DEFAULT_BINDER_INTERFACE NULL #endif /* @@ -73,6 +85,59 @@ struct json_object *main_config; static pid_t childpid; +/** + * Tiny helper around putenv: add the variable name=value + * + * @param name name of the variable to set + * @param value value to set to the variable + * + * @return 0 in case of success or -1 in case of error (with errno set to ENOMEM) + */ +static int addenv(const char *name, const char *value) +{ + char *head, *middle; + + head = malloc(2 + strlen(name) + strlen(value)); + if (head == NULL) { + errno = ENOMEM; + return -1; + } + middle = stpcpy(head, name); + middle[0] = '='; + strcpy(&middle[1], value); + return putenv(head); +} + +/** + * Tiny helper around addenv that export the real path + * + * @param name name of the variable to set + * @param path the path value to export to the variable + * + * @return 0 in case of success or -1 in case of error (with errno set to ENOMEM) + */ +static int addenv_realpath(const char *name, const char *path) +{ + char buffer[PATH_MAX]; + char *p = realpath(path, buffer); + return p ? addenv(name, p) : -1; +} + +/** + * Tiny helper around addenv that export an integer + * + * @param name name of the variable to set + * @param value the integer value to export + * + * @return 0 in case of success or -1 in case of error (with errno set to ENOMEM) + */ +static int addenv_int(const char *name, int value) +{ + char buffer[64]; + snprintf(buffer, sizeof buffer, "%d", value); + return addenv(name, buffer); +} + /*---------------------------------------------------------- | helpers for handling list of arguments +--------------------------------------------------------- */ @@ -172,13 +237,14 @@ static void setup_daemon() +--------------------------------------------------------- */ static void daemonize() { - int fd, daemon; + int fd = 0, daemon, nostdin; const char *output; pid_t pid; daemon = 0; output = NULL; wrap_json_unpack(main_config, "{s?b s?s}", "daemon", &daemon, "output", &output); + nostdin = 0; if (output) { fd = open(output, O_WRONLY | O_APPEND | O_CREAT, 0640); @@ -198,6 +264,8 @@ static void daemonize() } if (pid != 0) _exit(0); + + nostdin = 1; } /* closes the input */ @@ -210,8 +278,8 @@ static void daemonize() close(fd); } - /* after that ctrl+C still works */ - close(0); + if (nostdin) + close(0); /* except if 'daemon', ctrl+C still works after that */ } /*--------------------------------------------------------- @@ -290,8 +358,12 @@ static struct afb_hsrv *start_http_server() } if (afb_hreq_init_download_path(uploaddir)) { - ERROR("unable to set the upload directory %s", uploaddir); - return NULL; + static const char fallback_uploaddir[] = "/tmp"; + WARNING("unable to set the upload directory %s", uploaddir); + if (afb_hreq_init_download_path(fallback_uploaddir)) { + ERROR("unable to fallback to upload directory %s", fallback_uploaddir); + return NULL; + } } hsrv = afb_hsrv_create(); @@ -310,13 +382,20 @@ static struct afb_hsrv *start_http_server() NOTICE("Waiting port=%d rootdir=%s", http_port, rootdir); NOTICE("Browser URL= http://localhost:%d", http_port); - rc = afb_hsrv_start(hsrv, (uint16_t) http_port, 15); + rc = afb_hsrv_start(hsrv, 15); if (!rc) { ERROR("starting of httpd failed"); afb_hsrv_put(hsrv); return NULL; } + rc = afb_hsrv_add_interface_tcp(hsrv, DEFAULT_BINDER_INTERFACE, (uint16_t) http_port); + if (!rc) { + ERROR("setting interface failed"); + afb_hsrv_put(hsrv); + return NULL; + } + return hsrv; } @@ -324,6 +403,27 @@ static struct afb_hsrv *start_http_server() | execute_command +--------------------------------------------------------- */ +static void exit_at_end() +{ + exit(0); +} + +static void wait_child(int signum, void* arg) +{ + pid_t pid = (pid_t)(intptr_t)arg; + pid_t pidchld = childpid; + + if (pidchld == pid) { + childpid = 0; + if (!SELF_PGROUP) + killpg(pidchld, SIGKILL); + waitpid(pidchld, NULL, 0); + jobs_exit(exit_at_end); + } else { + waitpid(pid, NULL, 0); + } +} + static void on_sigchld(int signum, siginfo_t *info, void *uctx) { if (info->si_pid == childpid) { @@ -331,11 +431,9 @@ static void on_sigchld(int signum, siginfo_t *info, void *uctx) case CLD_EXITED: case CLD_KILLED: case CLD_DUMPED: - childpid = 0; - if (!SELF_PGROUP) - killpg(info->si_pid, SIGKILL); - waitpid(info->si_pid, NULL, 0); - exit(0); + jobs_queue_lazy(0, 0, wait_child, (void*)(intptr_t)info->si_pid); + default: + break; } } } @@ -480,7 +578,7 @@ static int execute_command() ERROR("port->txt failed"); } else { - /* instanciate arguments and environment */ + /* instantiate arguments and environment */ token = afb_session_initial_token(); args = instanciate_command_args(exec, port, token); if (args && instanciate_environ(port, token) >= 0) { @@ -602,8 +700,15 @@ static void run_startup_calls() static void start(int signum, void *arg) { - const char *tracereq, *traceapi, *traceevt, *traceses, *tracesvc, *traceditf, *traceglob; +#if WITH_AFB_HOOK + const char *tracereq = NULL, *traceapi = NULL, *traceevt = NULL, +#if !defined(REMOVE_LEGACY_TRACE) + *tracesvc = NULL, *traceditf = NULL, +#endif + *traceses = NULL, *traceglob = NULL; +#endif const char *workdir, *rootdir, *token, *rootapi; + struct json_object *settings; struct afb_hsrv *hsrv; int max_session_count, session_timeout, api_timeout; int no_httpd, http_port; @@ -617,17 +722,21 @@ static void start(int signum, void *arg) exit(1); } - token = rootapi = tracesvc = traceditf = tracereq = - traceapi = traceevt = traceses = traceglob = NULL; - no_httpd = http_port = 0; + settings = NULL; + no_httpd = 0; + http_port = -1; + rootapi = token = NULL; rc = wrap_json_unpack(main_config, "{" "ss ss s?s" "si si si" "s?b s?i s?s" +#if WITH_AFB_HOOK #if !defined(REMOVE_LEGACY_TRACE) "s?s s?s" #endif "s?s s?s s?s s?s s?s" +#endif + "s?o" "}", "rootdir", &rootdir, @@ -642,6 +751,7 @@ static void start(int signum, void *arg) "port", &http_port, "rootapi", &rootapi, +#if WITH_AFB_HOOK #if !defined(REMOVE_LEGACY_TRACE) "tracesvc", &tracesvc, "traceditf", &traceditf, @@ -650,13 +760,21 @@ static void start(int signum, void *arg) "traceapi", &traceapi, "traceevt", &traceevt, "traceses", &traceses, - "traceglob", &traceglob + "traceglob", &traceglob, +#endif + "set", &settings ); if (rc < 0) { ERROR("Unable to get start config"); exit(1); } + /* initialize session handling */ + if (afb_session_init(max_session_count, session_timeout, token)) { + ERROR("initialisation of session manager failed"); + goto error; + } + /* set the directories */ mkdir(workdir, S_IRWXU | S_IRGRP | S_IXGRP); if (chdir(workdir) < 0) { @@ -664,15 +782,34 @@ static void start(int signum, void *arg) goto error; } if (afb_common_rootdir_set(rootdir) < 0) { - ERROR("failed to set common root directory"); + ERROR("failed to set common root directory %s", rootdir); goto error; } - - /* configure the daemon */ - if (afb_session_init(max_session_count, session_timeout, token)) { - ERROR("initialisation of session manager failed"); + if (addenv_realpath("AFB_WORKDIR", "." /* resolved by realpath */) + || addenv_realpath("AFB_ROOTDIR", rootdir /* relative to current directory */)) { + ERROR("can't set DIR environment"); goto error; } + + /* setup HTTP */ + if (!no_httpd) { + if (http_port < 0) { + ERROR("no port is defined"); + goto error; + } + if (http_port == 0) { + ERROR("random port is not implemented"); + goto error; + } + if (addenv_int("AFB_PORT", http_port) + || addenv("AFB_TOKEN", afb_session_initial_token())) { + ERROR("can't set HTTP environment"); + goto error; + } + } + + /* configure the daemon */ + afb_export_set_config(settings); main_apiset = afb_apiset_create("main", api_timeout); if (!main_apiset) { ERROR("can't create main api set"); @@ -682,13 +819,14 @@ static void start(int signum, void *arg) ERROR("failed to setup monitor"); goto error; } -#if defined(WITH_SUPERVISION) +#if WITH_SUPERVISION if (afb_supervision_init(main_apiset, main_config) < 0) { ERROR("failed to setup supervision"); goto error; } #endif +#if WITH_AFB_HOOK /* install hooks */ if (tracereq) afb_hook_create_xreq(NULL, NULL, NULL, afb_hook_flags_xreq_from_text(tracereq), NULL, NULL); @@ -707,16 +845,17 @@ static void start(int signum, void *arg) afb_hook_create_session(NULL, afb_hook_flags_session_from_text(traceses), NULL, NULL); if (traceglob) afb_hook_create_global(afb_hook_flags_global_from_text(traceglob), NULL, NULL); +#endif - /* load bindings */ + /* load bindings and apis */ afb_debug("start-load"); +#if WITH_DYNAMIC_BINDING apiset_start_list("binding", afb_api_so_add_binding, "the binding"); apiset_start_list("ldpaths", afb_api_so_add_pathset_fails, "the binding path set"); apiset_start_list("weak-ldpaths", afb_api_so_add_pathset_nofails, "the weak binding path set"); +#endif apiset_start_list("auto-api", afb_autoset_add_any, "the automatic api path set"); - apiset_start_list("ws-server", afb_api_ws_add_server, "the afb-websocket service"); -#if defined(WITH_DBUS_TRANSPARENCY) - apiset_start_list("dbus-server", afb_api_dbus_add_server, "the afb-dbus service"); +#if WITH_DBUS_TRANSPARENCY apiset_start_list("dbus-client", afb_api_dbus_add_client, "the afb-dbus client"); #endif apiset_start_list("ws-client", afb_api_ws_add_client_weak, "the afb-websocket client"); @@ -731,14 +870,15 @@ static void start(int signum, void *arg) if (afb_apiset_start_all_services(main_apiset) < 0) goto error; + /* export started apis */ + apiset_start_list("ws-server", afb_api_ws_add_server, "the afb-websocket service"); +#if WITH_DBUS_TRANSPARENCY + apiset_start_list("dbus-server", afb_api_dbus_add_server, "the afb-dbus service"); +#endif + /* start the HTTP server */ afb_debug("start-http"); if (!no_httpd) { - if (http_port <= 0) { - ERROR("no port is defined"); - goto error; - } - if (!afb_hreq_init_cookie(http_port, rootapi, session_timeout)) { ERROR("initialisation of HTTP cookies failed"); goto error; @@ -760,6 +900,13 @@ static void start(int signum, void *arg) /* ready */ sd_notify(1, "READY=1"); + + /* activate the watchdog */ +#if HAS_WATCHDOG + if (watchdog_activate() < 0) + ERROR("can't start the watchdog"); +#endif + return; error: exit(1); @@ -772,15 +919,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)); + main_config = afb_args_parse(argc, argv); + 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"); @@ -794,7 +949,7 @@ int main(int argc, char *argv[]) afb_debug("main-start"); /* enter job processing */ - jobs_start(3, 0, 50, start, NULL); + jobs_start(3, 0, 100, start, NULL); WARNING("hoops returned from jobs_enter! [report bug]"); return 1; }