From b76d99d9e66f965b79dade55ab719d54a17e709c Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Mon, 28 Nov 2016 20:42:40 +0100 Subject: [PATCH] networkd: move event loop handling out of the manager (#4723) This will allow us to have several managers sharing an event loop and running in parallel, as if they were running in separate processes. The long term-aim is to allow networkd to be split into separate processes, so restructure the code to make this simpler. For now we drop the exit-on-idle logic, as this was anyway severely restricted at the moment. Once split, we will revisit this as it may then make more sense again. --- src/network/networkd-manager.c | 52 ++++-------------------------------------- src/network/networkd-manager.h | 4 ++-- src/network/networkd.c | 23 ++++++++++++++++--- src/network/test-network.c | 11 +++++++-- 4 files changed, 35 insertions(+), 55 deletions(-) diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 4e3f9e3..ea1c320 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -1042,7 +1042,7 @@ static int manager_dirty_handler(sd_event_source *s, void *userdata) { return 1; } -int manager_new(Manager **ret) { +int manager_new(Manager **ret, sd_event *event) { _cleanup_manager_free_ Manager *m = NULL; int r; @@ -1054,14 +1054,7 @@ int manager_new(Manager **ret) { if (!m->state_file) return -ENOMEM; - r = sd_event_default(&m->event); - if (r < 0) - return r; - - sd_event_set_watchdog(m->event, true); - - sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL); - sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL); + m->event = sd_event_ref(event); r = sd_event_add_post(m->event, NULL, manager_dirty_handler, m); if (r < 0) @@ -1137,33 +1130,7 @@ void manager_free(Manager *m) { free(m); } -static bool manager_check_idle(void *userdata) { - Manager *m = userdata; - Link *link; - Iterator i; - - assert(m); - - /* Check whether we are idle now. The only case when we decide to be idle is when there's only a loopback - * device around, for which we have no configuration, and which already left the PENDING state. In all other - * cases we are not idle. */ - - HASHMAP_FOREACH(link, m->links, i) { - /* We are not woken on udev activity, so let's just wait for the pending udev event */ - if (link->state == LINK_STATE_PENDING) - return false; - - if ((link->flags & IFF_LOOPBACK) == 0) - return false; - - if (link->network) - return false; - } - - return true; -} - -int manager_run(Manager *m) { +int manager_start(Manager *m) { Link *link; Iterator i; @@ -1177,18 +1144,7 @@ int manager_run(Manager *m) { HASHMAP_FOREACH(link, m->links, i) link_save(link); - if (m->bus) - return bus_event_loop_with_idle( - m->event, - m->bus, - "org.freedesktop.network1", - DEFAULT_EXIT_USEC, - manager_check_idle, - m); - else - /* failed to connect to the bus, so we lose exit-on-idle logic, - this should not happen except if dbus is not around at all */ - return sd_event_loop(m->event); + return 0; } int manager_load_config(Manager *m) { diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h index c81f505..e2447c2 100644 --- a/src/network/networkd-manager.h +++ b/src/network/networkd-manager.h @@ -76,11 +76,11 @@ static inline const DUID* link_duid(const Link *link) { extern const sd_bus_vtable manager_vtable[]; -int manager_new(Manager **ret); +int manager_new(Manager **ret, sd_event *event); void manager_free(Manager *m); int manager_connect_bus(Manager *m); -int manager_run(Manager *m); +int manager_start(Manager *m); int manager_load_config(Manager *m); bool manager_should_reload(Manager *m); diff --git a/src/network/networkd.c b/src/network/networkd.c index 2851432..fe60f1e 100644 --- a/src/network/networkd.c +++ b/src/network/networkd.c @@ -18,6 +18,7 @@ ***/ #include "sd-daemon.h" +#include "sd-event.h" #include "capability-util.h" #include "networkd-conf.h" @@ -26,6 +27,7 @@ #include "user-util.h" int main(int argc, char *argv[]) { + sd_event *event = NULL; _cleanup_manager_free_ Manager *m = NULL; const char *user = "systemd-network"; uid_t uid; @@ -78,7 +80,15 @@ int main(int argc, char *argv[]) { assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); - r = manager_new(&m); + r = sd_event_default(&event); + if (r < 0) + goto out; + + sd_event_set_watchdog(event, true); + sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL); + sd_event_add_signal(event, NULL, SIGINT, NULL, NULL); + + r = manager_new(&m, event); if (r < 0) { log_error_errno(r, "Could not create manager: %m"); goto out; @@ -118,22 +128,29 @@ int main(int argc, char *argv[]) { goto out; } + r = manager_start(m); + if (r < 0) { + log_error_errno(r, "Could not start manager: %m"); + goto out; + } + log_info("Enumeration completed"); sd_notify(false, "READY=1\n" "STATUS=Processing requests..."); - r = manager_run(m); + r = sd_event_loop(event); if (r < 0) { log_error_errno(r, "Event loop failed: %m"); goto out; } - out: sd_notify(false, "STOPPING=1\n" "STATUS=Shutting down..."); + sd_event_unref(event); + return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/src/network/test-network.c b/src/network/test-network.c index 93184a7..64d2f23 100644 --- a/src/network/test-network.c +++ b/src/network/test-network.c @@ -186,6 +186,7 @@ static void test_address_equality(void) { int main(void) { _cleanup_manager_free_ Manager *manager = NULL; + sd_event *event; struct udev *udev; struct udev_device *loopback; int r; @@ -194,11 +195,16 @@ int main(void) { test_deserialize_dhcp_routes(); test_address_equality(); - assert_se(manager_new(&manager) >= 0); + r = sd_event_default(&event); + assert_se(r >= 0); + + assert_se(manager_new(&manager, event) >= 0); r = test_load_config(manager); - if (r == -EPERM) + if (r == -EPERM) { + sd_event_unref(event); return EXIT_TEST_SKIP; + } udev = udev_new(); assert_se(udev); @@ -213,4 +219,5 @@ int main(void) { udev_device_unref(loopback); udev_unref(udev); + sd_event_unref(event); } -- 2.7.4