From 1437822638ff9468fa78c7cfe56f8f55f955a61d Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 26 Nov 2018 16:18:40 +0900 Subject: [PATCH 01/12] meson: rename sd_event_c to sd_event_sources --- src/libsystemd/meson.build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libsystemd/meson.build b/src/libsystemd/meson.build index 071691327b7..f441bb6972e 100644 --- a/src/libsystemd/meson.build +++ b/src/libsystemd/meson.build @@ -8,7 +8,7 @@ id128_sources = files(''' sd_daemon_c = files('sd-daemon/sd-daemon.c') -sd_event_c = files(''' +sd_event_sources = files(''' sd-event/event-source.h sd-event/event-util.c sd-event/event-util.h @@ -90,7 +90,7 @@ libsystemd_sources = files(''' sd-path/sd-path.c sd-resolve/sd-resolve.c sd-utf8/sd-utf8.c -'''.split()) + id128_sources + sd_daemon_c + sd_event_c + sd_login_c +'''.split()) + id128_sources + sd_daemon_c + sd_event_sources + sd_login_c disable_mempool_c = files('disable-mempool.c') From c157884f0917f4ecebfd5acb218ffb5034145c1c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 26 Nov 2018 17:55:56 +0900 Subject: [PATCH 02/12] sd-daemon: add notify_start() and notify_on_cleanup() helper function --- src/shared/daemon-util.h | 22 ++++++++++++++++++++++ src/shared/meson.build | 1 + 2 files changed, 23 insertions(+) create mode 100644 src/shared/daemon-util.h diff --git a/src/shared/daemon-util.h b/src/shared/daemon-util.h new file mode 100644 index 00000000000..5e9eca1d9e7 --- /dev/null +++ b/src/shared/daemon-util.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "sd-daemon.h" + +#define NOTIFY_READY "READY=1\n" "STATUS=Processing requests..." +#define NOTIFY_STOPPING "STOPPING=1\n" "STATUS=Shutting down..." + +static inline const char *notify_start(const char *start, const char *stop) { + if (start) + (void) sd_notify(false, start); + + return stop; +} + +/* This is intended to be used with _cleanup_ attribute. */ +static inline void notify_on_cleanup(const char **p) { + if (p) + (void) sd_notify(false, *p); +} diff --git a/src/shared/meson.build b/src/shared/meson.build index 5917d43ef9d..ca2e05325ee 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -41,6 +41,7 @@ shared_sources = files(''' cpu-set-util.h crypt-util.c crypt-util.h + daemon-util.h dev-setup.c dev-setup.h dissect-image.c From 1e88b8199b5f4d64367359772898068c2a69d76e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 26 Nov 2018 16:29:02 +0900 Subject: [PATCH 03/12] resolve: define main through macro --- src/resolve/resolved.c | 71 ++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 45 deletions(-) diff --git a/src/resolve/resolved.c b/src/resolve/resolved.c index 755477096d5..f4efddf8e5b 100644 --- a/src/resolve/resolved.c +++ b/src/resolve/resolved.c @@ -4,6 +4,8 @@ #include "sd-event.h" #include "capability-util.h" +#include "daemon-util.h" +#include "main-func.h" #include "mkdir.h" #include "resolved-conf.h" #include "resolved-manager.h" @@ -12,7 +14,8 @@ #include "signal-util.h" #include "user-util.h" -int main(int argc, char *argv[]) { +static int run(int argc, char *argv[]) { + _cleanup_(notify_on_cleanup) const char *notify_stop = NULL; _cleanup_(manager_freep) Manager *m = NULL; const char *user = "systemd-resolve"; uid_t uid; @@ -21,32 +24,23 @@ int main(int argc, char *argv[]) { log_setup_service(); - if (argc != 1) { - log_error("This program takes no arguments."); - r = -EINVAL; - goto finish; - } + if (argc != 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments."); umask(0022); r = mac_selinux_init(); - if (r < 0) { - log_error_errno(r, "SELinux setup failed: %m"); - goto finish; - } + if (r < 0) + return log_error_errno(r, "SELinux setup failed: %m"); r = get_user_creds(&user, &uid, &gid, NULL, NULL, 0); - if (r < 0) { - log_error_errno(r, "Cannot resolve user name %s: %m", user); - goto finish; - } + if (r < 0) + return log_error_errno(r, "Cannot resolve user name %s: %m", user); /* Always create the directory where resolv.conf will live */ r = mkdir_safe_label("/run/systemd/resolve", 0755, uid, gid, MKDIR_WARN_MODE); - if (r < 0) { - log_error_errno(r, "Could not create runtime directory: %m"); - goto finish; - } + if (r < 0) + return log_error_errno(r, "Could not create runtime directory: %m"); /* Drop privileges, but only if we have been started as root. If we are not running as root we assume most * privileges are already dropped. */ @@ -58,22 +52,18 @@ int main(int argc, char *argv[]) { (UINT64_C(1) << CAP_NET_BIND_SERVICE)| /* needed to bind on port 53 */ (UINT64_C(1) << CAP_SETPCAP) /* needed in order to drop the caps later */); if (r < 0) - goto finish; + return log_error_errno(r, "Failed to drop privileges: %m"); } assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGUSR1, SIGUSR2, SIGRTMIN+1, -1) >= 0); r = manager_new(&m); - if (r < 0) { - log_error_errno(r, "Could not create manager: %m"); - goto finish; - } + if (r < 0) + return log_error_errno(r, "Could not create manager: %m"); r = manager_start(m); - if (r < 0) { - log_error_errno(r, "Failed to start manager: %m"); - goto finish; - } + if (r < 0) + return log_error_errno(r, "Failed to start manager: %m"); /* Write finish default resolv.conf to avoid a dangling symlink */ (void) manager_write_resolv_conf(m); @@ -82,27 +72,18 @@ int main(int argc, char *argv[]) { /* Let's drop the remaining caps now */ r = capability_bounding_set_drop(0, true); - if (r < 0) { - log_error_errno(r, "Failed to drop remaining caps: %m"); - goto finish; - } + if (r < 0) + return log_error_errno(r, "Failed to drop remaining caps: %m"); - sd_notify(false, - "READY=1\n" - "STATUS=Processing requests..."); + notify_stop = notify_start(NOTIFY_READY, NOTIFY_STOPPING); r = sd_event_loop(m->event); - if (r < 0) { - log_error_errno(r, "Event loop failed: %m"); - goto finish; - } + if (r < 0) + return log_error_errno(r, "Event loop failed: %m"); - sd_event_get_exit_code(m->event, &r); + (void) sd_event_get_exit_code(m->event, &r); -finish: - sd_notify(false, - "STOPPING=1\n" - "STATUS=Shutting down..."); - - return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; + return r; } + +DEFINE_MAIN_FUNCTION(run); From 2362a8f54790d9af35da723952d5e8e37229592f Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 26 Nov 2018 16:37:52 +0900 Subject: [PATCH 04/12] network: define main through macro --- src/network/networkd.c | 86 +++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 55 deletions(-) diff --git a/src/network/networkd.c b/src/network/networkd.c index 4fa5533c601..fcecafe0839 100644 --- a/src/network/networkd.c +++ b/src/network/networkd.c @@ -4,13 +4,16 @@ #include "sd-event.h" #include "capability-util.h" +#include "daemon-util.h" +#include "main-func.h" #include "mkdir.h" #include "networkd-conf.h" #include "networkd-manager.h" #include "signal-util.h" #include "user-util.h" -int main(int argc, char *argv[]) { +static int run(int argc, char *argv[]) { + _cleanup_(notify_on_cleanup) const char *notify_message = NULL; _cleanup_(manager_freep) Manager *m = NULL; const char *user = "systemd-network"; uid_t uid; @@ -21,17 +24,12 @@ int main(int argc, char *argv[]) { umask(0022); - if (argc != 1) { - log_error("This program takes no arguments."); - r = -EINVAL; - goto out; - } + if (argc != 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments."); r = get_user_creds(&user, &uid, &gid, NULL, NULL, 0); - if (r < 0) { - log_error_errno(r, "Cannot resolve user name %s: %m", user); - goto out; - } + if (r < 0) + return log_error_errno(r, "Cannot resolve user name %s: %m", user); /* Create runtime directory. This is not necessary when networkd is * started with "RuntimeDirectory=systemd/netif", or after @@ -49,7 +47,7 @@ int main(int argc, char *argv[]) { (1ULL << CAP_NET_BROADCAST) | (1ULL << CAP_NET_RAW)); if (r < 0) - goto out; + return log_error_errno(r, "Failed to drop privileges: %m"); } /* Always create the directories people can create inotify watches in. @@ -70,72 +68,50 @@ int main(int argc, char *argv[]) { assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); r = manager_new(&m); - if (r < 0) { - log_error_errno(r, "Could not create manager: %m"); - goto out; - } + if (r < 0) + return log_error_errno(r, "Could not create manager: %m"); r = manager_connect_bus(m); - if (r < 0) { - log_error_errno(r, "Could not connect to bus: %m"); - goto out; - } + if (r < 0) + return log_error_errno(r, "Could not connect to bus: %m"); r = manager_parse_config_file(m); if (r < 0) log_warning_errno(r, "Failed to parse configuration file: %m"); r = manager_load_config(m); - if (r < 0) { - log_error_errno(r, "Could not load configuration files: %m"); - goto out; - } + if (r < 0) + return log_error_errno(r, "Could not load configuration files: %m"); r = manager_rtnl_enumerate_links(m); - if (r < 0) { - log_error_errno(r, "Could not enumerate links: %m"); - goto out; - } + if (r < 0) + return log_error_errno(r, "Could not enumerate links: %m"); r = manager_rtnl_enumerate_addresses(m); - if (r < 0) { - log_error_errno(r, "Could not enumerate addresses: %m"); - goto out; - } + if (r < 0) + return log_error_errno(r, "Could not enumerate addresses: %m"); r = manager_rtnl_enumerate_routes(m); - if (r < 0) { - log_error_errno(r, "Could not enumerate routes: %m"); - goto out; - } + if (r < 0) + return log_error_errno(r, "Could not enumerate routes: %m"); r = manager_rtnl_enumerate_rules(m); - if (r < 0) { - log_error_errno(r, "Could not enumerate rules: %m"); - goto out; - } + if (r < 0) + return log_error_errno(r, "Could not enumerate rules: %m"); r = manager_start(m); - if (r < 0) { - log_error_errno(r, "Could not start manager: %m"); - goto out; - } + if (r < 0) + return log_error_errno(r, "Could not start manager: %m"); log_info("Enumeration completed"); - sd_notify(false, - "READY=1\n" - "STATUS=Processing requests..."); + notify_message = notify_start(NOTIFY_READY, NOTIFY_STOPPING); r = sd_event_loop(m->event); - if (r < 0) { - log_error_errno(r, "Event loop failed: %m"); - goto out; - } -out: - sd_notify(false, - "STOPPING=1\n" - "STATUS=Shutting down..."); + if (r < 0) + return log_error_errno(r, "Event loop failed: %m"); - return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; + return 0; } + +DEFINE_MAIN_FUNCTION(run); From 82310c798176281178fc51e02da48985942cf262 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 26 Nov 2018 16:47:07 +0900 Subject: [PATCH 05/12] timesync: define main through macro --- src/timesync/timesyncd.c | 66 ++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 39 deletions(-) diff --git a/src/timesync/timesyncd.c b/src/timesync/timesyncd.c index 40552955556..70774d757be 100644 --- a/src/timesync/timesyncd.c +++ b/src/timesync/timesyncd.c @@ -5,8 +5,10 @@ #include "capability-util.h" #include "clock-util.h" +#include "daemon-util.h" #include "fd-util.h" #include "fs-util.h" +#include "main-func.h" #include "mkdir.h" #include "network-util.h" #include "process-util.h" @@ -83,7 +85,8 @@ settime: return 0; } -int main(int argc, char *argv[]) { +static int run(int argc, char *argv[]) { + _cleanup_(notify_on_cleanup) const char *notify_message = NULL; _cleanup_(manager_freep) Manager *m = NULL; const char *user = "systemd-timesync"; uid_t uid, uid_current; @@ -95,48 +98,39 @@ int main(int argc, char *argv[]) { umask(0022); - if (argc != 1) { - log_error("This program does not take arguments."); - r = -EINVAL; - goto finish; - } + if (argc != 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program does not take arguments."); uid = uid_current = geteuid(); gid = getegid(); if (uid_current == 0) { r = get_user_creds(&user, &uid, &gid, NULL, NULL, 0); - if (r < 0) { - log_error_errno(r, "Cannot resolve user name %s: %m", user); - goto finish; - } + if (r < 0) + return log_error_errno(r, "Cannot resolve user name %s: %m", user); } r = load_clock_timestamp(uid, gid); if (r < 0) - goto finish; + return r; /* Drop privileges, but only if we have been started as root. If we are not running as root we assume all * privileges are already dropped. */ if (uid_current == 0) { r = drop_privileges(uid, gid, (1ULL << CAP_SYS_TIME)); if (r < 0) - goto finish; + return log_error_errno(r, "Failed to drop privileges: %m"); } assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); r = manager_new(&m); - if (r < 0) { - log_error_errno(r, "Failed to allocate manager: %m"); - goto finish; - } + if (r < 0) + return log_error_errno(r, "Failed to allocate manager: %m"); r = manager_connect_bus(m); - if (r < 0) { - log_error_errno(r, "Could not connect to bus: %m"); - goto finish; - } + if (r < 0) + return log_error_errno(r, "Could not connect to bus: %m"); if (clock_is_localtime(NULL) > 0) { log_info("The system is configured to read the RTC time in the local time zone. " @@ -149,27 +143,24 @@ int main(int argc, char *argv[]) { log_warning_errno(r, "Failed to parse configuration file: %m"); r = manager_parse_fallback_string(m, NTP_SERVERS); - if (r < 0) { - log_error_errno(r, "Failed to parse fallback server strings: %m"); - goto finish; - } + if (r < 0) + return log_error_errno(r, "Failed to parse fallback server strings: %m"); log_debug("systemd-timesyncd running as pid " PID_FMT, getpid_cached()); - sd_notify(false, - "READY=1\n" - "STATUS=Daemon is running"); + + notify_message = notify_start("READY=1\n" + "STATUS=Daemon is running", + NOTIFY_STOPPING); if (network_is_online()) { r = manager_connect(m); if (r < 0) - goto finish; + return r; } r = sd_event_loop(m->event); - if (r < 0) { - log_error_errno(r, "Failed to run event loop: %m"); - goto finish; - } + if (r < 0) + return log_error_errno(r, "Failed to run event loop: %m"); /* if we got an authoritative time, store it in the file system */ if (m->sync) { @@ -178,12 +169,9 @@ int main(int argc, char *argv[]) { log_debug_errno(r, "Failed to touch %s, ignoring: %m", CLOCK_FILE); } - sd_event_get_exit_code(m->event, &r); + (void) sd_event_get_exit_code(m->event, &r); -finish: - sd_notify(false, - "STOPPING=1\n" - "STATUS=Shutting down..."); - - return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; + return r; } + +DEFINE_MAIN_FUNCTION(run); From c03a80c41945687ca5deac159a164859ec45511e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 26 Nov 2018 16:56:58 +0900 Subject: [PATCH 06/12] wait-online: define main through macro --- src/network/wait-online/wait-online.c | 49 ++++++++++++--------------- 1 file changed, 21 insertions(+), 28 deletions(-) diff --git a/src/network/wait-online/wait-online.c b/src/network/wait-online/wait-online.c index 7f30862bbfc..71b6cf6b877 100644 --- a/src/network/wait-online/wait-online.c +++ b/src/network/wait-online/wait-online.c @@ -4,6 +4,8 @@ #include "sd-daemon.h" +#include "daemon-util.h" +#include "main-func.h" #include "manager.h" #include "pretty-print.h" #include "signal-util.h" @@ -14,6 +16,9 @@ static usec_t arg_timeout = 120 * USEC_PER_SEC; static char **arg_interfaces = NULL; static char **arg_ignore = NULL; +STATIC_DESTRUCTOR_REGISTER(arg_interfaces, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_ignore, strv_freep); + static int help(void) { _cleanup_free_ char *link = NULL; int r; @@ -105,7 +110,8 @@ static int parse_argv(int argc, char *argv[]) { return 1; } -int main(int argc, char *argv[]) { +static int run(int argc, char *argv[]) { + _cleanup_(notify_on_cleanup) const char *notify_message = NULL; _cleanup_(manager_freep) Manager *m = NULL; int r; @@ -123,37 +129,24 @@ int main(int argc, char *argv[]) { assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); r = manager_new(&m, arg_interfaces, arg_ignore, arg_timeout); - if (r < 0) { - log_error_errno(r, "Could not create manager: %m"); - goto finish; - } + if (r < 0) + return log_error_errno(r, "Could not create manager: %m"); - if (manager_all_configured(m)) { - r = 0; - goto finish; - } + if (manager_all_configured(m)) + goto success; - sd_notify(false, - "READY=1\n" - "STATUS=Waiting for network connections..."); + notify_message = notify_start("READY=1\n" + "STATUS=Waiting for network connections...", + "STATUS=Failed to wait for network connectivity..."); r = sd_event_loop(m->event); - if (r < 0) { - log_error_errno(r, "Event loop failed: %m"); - goto finish; - } + if (r < 0) + return log_error_errno(r, "Event loop failed: %m"); -finish: - strv_free(arg_interfaces); - strv_free(arg_ignore); +success: + notify_message = "STATUS=All interfaces configured..."; - if (r >= 0) { - sd_notify(false, "STATUS=All interfaces configured..."); - - return EXIT_SUCCESS; - } else { - sd_notify(false, "STATUS=Failed waiting for network connectivity..."); - - return EXIT_FAILURE; - } + return 0; } + +DEFINE_MAIN_FUNCTION(run); From 0d2a1a2085282d6226ecab284dfdda44a44bd53e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 26 Nov 2018 05:13:00 +0900 Subject: [PATCH 07/12] journal-gateway: use _cleanup_ attribute to stop microhttpd daemon --- src/journal-remote/journal-gatewayd.c | 5 +---- src/journal-remote/microhttpd-util.h | 2 ++ 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c index 69bc447920e..b779a521d51 100644 --- a/src/journal-remote/journal-gatewayd.c +++ b/src/journal-remote/journal-gatewayd.c @@ -982,7 +982,7 @@ static int parse_argv(int argc, char *argv[]) { } int main(int argc, char *argv[]) { - struct MHD_Daemon *d = NULL; + _cleanup_(MHD_stop_daemonp) struct MHD_Daemon *d = NULL; int r, n; log_setup_service(); @@ -1068,8 +1068,5 @@ int main(int argc, char *argv[]) { r = EXIT_SUCCESS; finish: - if (d) - MHD_stop_daemon(d); - return r; } diff --git a/src/journal-remote/microhttpd-util.h b/src/journal-remote/microhttpd-util.h index a50a2a75c7f..364cd0f7cfd 100644 --- a/src/journal-remote/microhttpd-util.h +++ b/src/journal-remote/microhttpd-util.h @@ -73,3 +73,5 @@ int check_permissions(struct MHD_Connection *connection, int *code, char **hostn * interesting events without overwhelming detail. */ int setup_gnutls_logger(char **categories); + +DEFINE_TRIVIAL_CLEANUP_FUNC(struct MHD_Daemon*, MHD_stop_daemon); From 29cd4c8ffbd40d88c0c65c81bda6a6c205eb5ba2 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 26 Nov 2018 05:21:50 +0900 Subject: [PATCH 08/12] journal-gateway: define main through macro --- src/journal-remote/journal-gatewayd.c | 134 +++++++++++++------------- 1 file changed, 66 insertions(+), 68 deletions(-) diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c index b779a521d51..4185af63e19 100644 --- a/src/journal-remote/journal-gatewayd.c +++ b/src/journal-remote/journal-gatewayd.c @@ -18,6 +18,7 @@ #include "hostname-util.h" #include "log.h" #include "logs-show.h" +#include "main-func.h" #include "microhttpd-util.h" #include "os-util.h" #include "parse-util.h" @@ -31,7 +32,11 @@ static char *arg_key_pem = NULL; static char *arg_cert_pem = NULL; static char *arg_trust_pem = NULL; -static char *arg_directory = NULL; +static const char *arg_directory = NULL; + +STATIC_DESTRUCTOR_REGISTER(arg_key_pem, freep); +STATIC_DESTRUCTOR_REGISTER(arg_cert_pem, freep); +STATIC_DESTRUCTOR_REGISTER(arg_trust_pem, freep); typedef struct RequestMeta { sd_journal *journal; @@ -981,92 +986,85 @@ static int parse_argv(int argc, char *argv[]) { return 1; } -int main(int argc, char *argv[]) { +static int run(int argc, char *argv[]) { _cleanup_(MHD_stop_daemonp) struct MHD_Daemon *d = NULL; + struct MHD_OptionItem opts[] = { + { MHD_OPTION_NOTIFY_COMPLETED, + (intptr_t) request_meta_free, NULL }, + { MHD_OPTION_EXTERNAL_LOGGER, + (intptr_t) microhttpd_logger, NULL }, + { MHD_OPTION_END, 0, NULL }, + { MHD_OPTION_END, 0, NULL }, + { MHD_OPTION_END, 0, NULL }, + { MHD_OPTION_END, 0, NULL }, + { MHD_OPTION_END, 0, NULL }, + }; + int opts_pos = 2; + + /* We force MHD_USE_ITC here, in order to make sure + * libmicrohttpd doesn't use shutdown() on our listening + * socket, which would break socket re-activation. See + * + * https://lists.gnu.org/archive/html/libmicrohttpd/2015-09/msg00014.html + * https://github.com/systemd/systemd/pull/1286 + */ + + int flags = + MHD_USE_DEBUG | + MHD_USE_DUAL_STACK | + MHD_USE_ITC | + MHD_USE_POLL_INTERNAL_THREAD | + MHD_USE_THREAD_PER_CONNECTION; int r, n; log_setup_service(); r = parse_argv(argc, argv); - if (r < 0) - return EXIT_FAILURE; - if (r == 0) - return EXIT_SUCCESS; + if (r <= 0) + return r; sigbus_install(); r = setup_gnutls_logger(NULL); if (r < 0) - return EXIT_FAILURE; + return r; n = sd_listen_fds(1); - if (n < 0) { - log_error_errno(n, "Failed to determine passed sockets: %m"); - goto finish; - } else if (n > 1) { - log_error("Can't listen on more than one socket."); - goto finish; - } else { - struct MHD_OptionItem opts[] = { - { MHD_OPTION_NOTIFY_COMPLETED, - (intptr_t) request_meta_free, NULL }, - { MHD_OPTION_EXTERNAL_LOGGER, - (intptr_t) microhttpd_logger, NULL }, - { MHD_OPTION_END, 0, NULL }, - { MHD_OPTION_END, 0, NULL }, - { MHD_OPTION_END, 0, NULL }, - { MHD_OPTION_END, 0, NULL }, - { MHD_OPTION_END, 0, NULL }}; - int opts_pos = 2; + if (n < 0) + return log_error_errno(n, "Failed to determine passed sockets: %m"); + if (n > 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Can't listen on more than one socket."); - /* We force MHD_USE_ITC here, in order to make sure - * libmicrohttpd doesn't use shutdown() on our listening - * socket, which would break socket re-activation. See - * - * https://lists.gnu.org/archive/html/libmicrohttpd/2015-09/msg00014.html - * https://github.com/systemd/systemd/pull/1286 - */ + if (n == 1) + opts[opts_pos++] = (struct MHD_OptionItem) + { MHD_OPTION_LISTEN_SOCKET, SD_LISTEN_FDS_START }; - int flags = - MHD_USE_DEBUG | - MHD_USE_DUAL_STACK | - MHD_USE_ITC | - MHD_USE_POLL_INTERNAL_THREAD | - MHD_USE_THREAD_PER_CONNECTION; - - if (n > 0) - opts[opts_pos++] = (struct MHD_OptionItem) - {MHD_OPTION_LISTEN_SOCKET, SD_LISTEN_FDS_START}; - if (arg_key_pem) { - assert(arg_cert_pem); - opts[opts_pos++] = (struct MHD_OptionItem) - {MHD_OPTION_HTTPS_MEM_KEY, 0, arg_key_pem}; - opts[opts_pos++] = (struct MHD_OptionItem) - {MHD_OPTION_HTTPS_MEM_CERT, 0, arg_cert_pem}; - flags |= MHD_USE_TLS; - } - if (arg_trust_pem) { - assert(flags & MHD_USE_TLS); - opts[opts_pos++] = (struct MHD_OptionItem) - {MHD_OPTION_HTTPS_MEM_TRUST, 0, arg_trust_pem}; - } - - d = MHD_start_daemon(flags, 19531, - NULL, NULL, - request_handler, NULL, - MHD_OPTION_ARRAY, opts, - MHD_OPTION_END); + if (arg_key_pem) { + assert(arg_cert_pem); + opts[opts_pos++] = (struct MHD_OptionItem) + { MHD_OPTION_HTTPS_MEM_KEY, 0, arg_key_pem }; + opts[opts_pos++] = (struct MHD_OptionItem) + { MHD_OPTION_HTTPS_MEM_CERT, 0, arg_cert_pem }; + flags |= MHD_USE_TLS; } - if (!d) { - log_error("Failed to start daemon!"); - goto finish; + if (arg_trust_pem) { + assert(flags & MHD_USE_TLS); + opts[opts_pos++] = (struct MHD_OptionItem) + { MHD_OPTION_HTTPS_MEM_TRUST, 0, arg_trust_pem }; } + d = MHD_start_daemon(flags, 19531, + NULL, NULL, + request_handler, NULL, + MHD_OPTION_ARRAY, opts, + MHD_OPTION_END); + if (!d) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to start daemon!"); + pause(); - r = EXIT_SUCCESS; - -finish: - return r; + return 0; } + +DEFINE_MAIN_FUNCTION(run); From c9ed608679b26d05782d43a571da2979b537389e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 26 Nov 2018 05:24:55 +0900 Subject: [PATCH 09/12] journal-upload: use _cleanup_ attribute to clear uploader --- src/journal-remote/journal-upload.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c index 7f08809c544..fd282ca19c8 100644 --- a/src/journal-remote/journal-upload.c +++ b/src/journal-remote/journal-upload.c @@ -762,7 +762,7 @@ static int open_journal(sd_journal **j) { } int main(int argc, char **argv) { - Uploader u; + _cleanup_(destroy_uploader) Uploader u = {}; int r; bool use_journal; @@ -853,8 +853,6 @@ cleanup: "STOPPING=1\n" "STATUS=Shutting down..."); - destroy_uploader(&u); - finish: return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE; } From f36bb1e182a558d284db488d8cbd67c3563fe2eb Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 26 Nov 2018 17:35:04 +0900 Subject: [PATCH 10/12] journal-upload: define main through macro --- src/journal-remote/journal-upload.c | 53 +++++++++++++---------------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c index fd282ca19c8..1e08fcc5541 100644 --- a/src/journal-remote/journal-upload.c +++ b/src/journal-remote/journal-upload.c @@ -10,6 +10,7 @@ #include "alloc-util.h" #include "conf-parser.h" +#include "daemon-util.h" #include "def.h" #include "env-file.h" #include "fd-util.h" @@ -18,6 +19,7 @@ #include "glob-util.h" #include "journal-upload.h" #include "log.h" +#include "main-func.h" #include "mkdir.h" #include "parse-util.h" #include "pretty-print.h" @@ -761,10 +763,11 @@ static int open_journal(sd_journal **j) { return r; } -int main(int argc, char **argv) { +static int run(int argc, char **argv) { + _cleanup_(notify_on_cleanup) const char *notify_message = NULL; _cleanup_(destroy_uploader) Uploader u = {}; - int r; bool use_journal; + int r; log_show_color(true); log_parse_environment(); @@ -774,23 +777,23 @@ int main(int argc, char **argv) { r = parse_config(); if (r < 0) - goto finish; + return r; r = parse_argv(argc, argv); if (r <= 0) - goto finish; + return r; sigbus_install(); r = setup_uploader(&u, arg_url, arg_save_state); if (r < 0) - goto cleanup; + return r; sd_event_set_watchdog(u.events, true); r = check_cursor_updating(&u); if (r < 0) - goto cleanup; + return r; log_debug("%s running as pid "PID_FMT, program_invocation_short_name, getpid_cached()); @@ -800,59 +803,51 @@ int main(int argc, char **argv) { sd_journal *j; r = open_journal(&j); if (r < 0) - goto finish; + return r; r = open_journal_for_upload(&u, j, arg_cursor ?: u.last_cursor, arg_cursor ? arg_after_cursor : true, !!arg_follow); if (r < 0) - goto finish; + return r; } - sd_notify(false, - "READY=1\n" - "STATUS=Processing input..."); + notify_message = notify_start("READY=1\n" + "STATUS=Processing input...", + NOTIFY_STOPPING); for (;;) { r = sd_event_get_state(u.events); if (r < 0) - break; + return r; if (r == SD_EVENT_FINISHED) - break; + return 0; if (use_journal) { if (!u.journal) - break; + return 0; r = check_journal_input(&u); } else if (u.input < 0 && !use_journal) { if (optind >= argc) - break; + return 0; log_debug("Using %s as input.", argv[optind]); r = open_file_for_upload(&u, argv[optind++]); } if (r < 0) - goto cleanup; + return r; if (u.uploading) { r = perform_upload(&u); if (r < 0) - break; + return r; } r = sd_event_run(u.events, u.timeout); - if (r < 0) { - log_error_errno(r, "Failed to run event loop: %m"); - break; - } + if (r < 0) + return log_error_errno(r, "Failed to run event loop: %m"); } - -cleanup: - sd_notify(false, - "STOPPING=1\n" - "STATUS=Shutting down..."); - -finish: - return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE; } + +DEFINE_MAIN_FUNCTION(run); From 94952201e1ba70ce961a1c398b3bc3822b6943f4 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 26 Nov 2018 17:50:52 +0900 Subject: [PATCH 11/12] journal-remote: destroy RemoteServer object by using _cleanup_ attribute --- src/journal-remote/journal-remote-main.c | 4 +--- src/journal-remote/journal-remote.c | 3 +-- src/journal-remote/journal-remote.h | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/journal-remote/journal-remote-main.c b/src/journal-remote/journal-remote-main.c index b82d4b4a1b6..655c099d678 100644 --- a/src/journal-remote/journal-remote-main.c +++ b/src/journal-remote/journal-remote-main.c @@ -1062,7 +1062,7 @@ static int load_certificates(char **key, char **cert, char **trust) { } int main(int argc, char **argv) { - RemoteServer s = {}; + _cleanup_(journal_remote_server_destroy) RemoteServer s = {}; int r; _cleanup_free_ char *key = NULL, *cert = NULL, *trust = NULL; @@ -1126,8 +1126,6 @@ int main(int argc, char **argv) { "STATUS=Shutting down after writing %" PRIu64 " entries...", s.event_count); log_info("Finishing after writing %" PRIu64 " entries", s.event_count); - journal_remote_server_destroy(&s); - free(arg_key); free(arg_cert); free(arg_trust); diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c index 1f3cdb932f7..3c0916c4383 100644 --- a/src/journal-remote/journal-remote.c +++ b/src/journal-remote/journal-remote.c @@ -346,7 +346,7 @@ static void MHDDaemonWrapper_free(MHDDaemonWrapper *d) { } #endif -RemoteServer* journal_remote_server_destroy(RemoteServer *s) { +void journal_remote_server_destroy(RemoteServer *s) { size_t i; #if HAVE_MICROHTTPD @@ -370,7 +370,6 @@ RemoteServer* journal_remote_server_destroy(RemoteServer *s) { journal_remote_server_global = NULL; /* fds that we're listening on remain open... */ - return NULL; } /********************************************************************** diff --git a/src/journal-remote/journal-remote.h b/src/journal-remote/journal-remote.h index e083ea9c749..4c25d43abf9 100644 --- a/src/journal-remote/journal-remote.h +++ b/src/journal-remote/journal-remote.h @@ -62,4 +62,4 @@ int journal_remote_handle_raw_source( uint32_t revents, RemoteServer *s); -RemoteServer* journal_remote_server_destroy(RemoteServer *s); +void journal_remote_server_destroy(RemoteServer *s); From d8dd35fd314d838acb9c9f7ada87d06ef0a9a25a Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 26 Nov 2018 17:51:32 +0900 Subject: [PATCH 12/12] journal-remote: define main through macro Also, this fixes memleaks on failure. --- src/journal-remote/journal-remote-main.c | 83 +++++++++++++----------- 1 file changed, 45 insertions(+), 38 deletions(-) diff --git a/src/journal-remote/journal-remote-main.c b/src/journal-remote/journal-remote-main.c index 655c099d678..e1748cb46b8 100644 --- a/src/journal-remote/journal-remote-main.c +++ b/src/journal-remote/journal-remote-main.c @@ -6,11 +6,13 @@ #include "sd-daemon.h" #include "conf-parser.h" +#include "daemon-util.h" #include "def.h" #include "fd-util.h" #include "fileio.h" #include "journal-remote-write.h" #include "journal-remote.h" +#include "main-func.h" #include "pretty-print.h" #include "process-util.h" #include "rlimit-util.h" @@ -24,25 +26,30 @@ #define CERT_FILE CERTIFICATE_ROOT "/certs/journal-remote.pem" #define TRUST_FILE CERTIFICATE_ROOT "/ca/trusted.pem" -static char* arg_url = NULL; -static char* arg_getter = NULL; -static char* arg_listen_raw = NULL; -static char* arg_listen_http = NULL; -static char* arg_listen_https = NULL; -static char** arg_files = NULL; +static const char* arg_url = NULL; +static const char* arg_getter = NULL; +static const char* arg_listen_raw = NULL; +static const char* arg_listen_http = NULL; +static const char* arg_listen_https = NULL; +static char** arg_files = NULL; /* Do not free this. */ static int arg_compress = true; static int arg_seal = false; static int http_socket = -1, https_socket = -1; static char** arg_gnutls_log = NULL; static JournalWriteSplitMode arg_split_mode = _JOURNAL_WRITE_SPLIT_INVALID; -static char* arg_output = NULL; +static const char* arg_output = NULL; static char *arg_key = NULL; static char *arg_cert = NULL; static char *arg_trust = NULL; static bool arg_trust_all = false; +STATIC_DESTRUCTOR_REGISTER(arg_gnutls_log, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_key, freep); +STATIC_DESTRUCTOR_REGISTER(arg_cert, freep); +STATIC_DESTRUCTOR_REGISTER(arg_trust, freep); + static const char* const journal_write_split_mode_table[_JOURNAL_WRITE_SPLIT_MAX] = { [JOURNAL_WRITE_SPLIT_NONE] = "none", [JOURNAL_WRITE_SPLIT_HOST] = "host", @@ -615,8 +622,7 @@ static int create_remoteserver( } if (arg_url) { - const char *url; - char *hostname; + const char *url, *hostname; if (!strstr(arg_url, "/entries")) { if (endswith(arg_url, "/")) @@ -637,7 +643,7 @@ static int create_remoteserver( hostname = strndupa(hostname, strcspn(hostname, "/:")); - r = journal_remote_add_source(s, fd, hostname, false); + r = journal_remote_add_source(s, fd, (char *) hostname, false); if (r < 0) return r; } @@ -1061,10 +1067,11 @@ static int load_certificates(char **key, char **cert, char **trust) { return 0; } -int main(int argc, char **argv) { +static int run(int argc, char **argv) { + _cleanup_(notify_on_cleanup) const char *notify_message = NULL; _cleanup_(journal_remote_server_destroy) RemoteServer s = {}; - int r; _cleanup_free_ char *key = NULL, *cert = NULL, *trust = NULL; + int r; log_show_color(true); log_parse_environment(); @@ -1074,61 +1081,61 @@ int main(int argc, char **argv) { r = parse_config(); if (r < 0) - return EXIT_FAILURE; + return r; r = parse_argv(argc, argv); if (r <= 0) - return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE; + return r; if (arg_listen_http || arg_listen_https) { r = setup_gnutls_logger(arg_gnutls_log); if (r < 0) - return EXIT_FAILURE; + return r; } if (arg_listen_https || https_socket >= 0) { - if (load_certificates(&key, &cert, &trust) < 0) - return EXIT_FAILURE; + r = load_certificates(&key, &cert, &trust); + if (r < 0) + return r; + s.check_trust = !arg_trust_all; } - if (create_remoteserver(&s, key, cert, trust) < 0) - return EXIT_FAILURE; + r = create_remoteserver(&s, key, cert, trust); + if (r < 0) + return r; r = sd_event_set_watchdog(s.events, true); if (r < 0) - log_error_errno(r, "Failed to enable watchdog: %m"); - else - log_debug("Watchdog is %sd.", enable_disable(r > 0)); + return log_error_errno(r, "Failed to enable watchdog: %m"); + + log_debug("Watchdog is %sd.", enable_disable(r > 0)); log_debug("%s running as pid "PID_FMT, program_invocation_short_name, getpid_cached()); - sd_notify(false, - "READY=1\n" - "STATUS=Processing requests..."); + + notify_message = notify_start(NOTIFY_READY, NOTIFY_STOPPING); while (s.active) { r = sd_event_get_state(s.events); if (r < 0) - break; + return r; if (r == SD_EVENT_FINISHED) break; r = sd_event_run(s.events, -1); - if (r < 0) { - log_error_errno(r, "Failed to run event loop: %m"); - break; - } + if (r < 0) + return log_error_errno(r, "Failed to run event loop: %m"); } - sd_notifyf(false, - "STOPPING=1\n" - "STATUS=Shutting down after writing %" PRIu64 " entries...", s.event_count); + notify_message = NULL; + (void) sd_notifyf(false, + "STOPPING=1\n" + "STATUS=Shutting down after writing %" PRIu64 " entries...", s.event_count); + log_info("Finishing after writing %" PRIu64 " entries", s.event_count); - free(arg_key); - free(arg_cert); - free(arg_trust); - - return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE; + return 0; } + +DEFINE_MAIN_FUNCTION(run);