]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
networkd,resolved: make use of watch_bind feature to connect to the bus
authorLennart Poettering <lennart@poettering.net>
Tue, 19 Dec 2017 14:54:30 +0000 (15:54 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 5 Jan 2018 12:58:32 +0000 (13:58 +0100)
The changes both networkd and resolved to make use of the watch_bind
feature of sd-bus to connect to the system bus. This way, both daemons
can be started during early boot, and automatically and instantly
connect to the system bus as it becomes available.

This replaces prior code that used a time-based retry logic to connect
to the bus.

src/network/networkd-manager.c
src/network/networkd-manager.h
src/resolve/resolved-bus.c
src/shared/bus-util.c
src/shared/bus-util.h
src/systemd/sd-bus.h

index 79d58dd0994c615958874c170b08a35682d1f6f7..4733dd5177b80c5bfc6726833d838c3fb847c91b 100644 (file)
@@ -82,19 +82,6 @@ static int setup_default_address_pool(Manager *m) {
         return 0;
 }
 
-static int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) {
-        Manager *m = userdata;
-
-        assert(s);
-        assert(m);
-
-        m->bus_retry_event_source = sd_event_source_unref(m->bus_retry_event_source);
-
-        manager_connect_bus(m);
-
-        return 0;
-}
-
 static int manager_reset_all(Manager *m) {
         Link *link;
         Iterator i;
@@ -116,6 +103,7 @@ static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_b
         int b, r;
 
         assert(message);
+        assert(m);
 
         r = sd_bus_message_read(message, "b", &b);
         if (r < 0) {
@@ -133,34 +121,32 @@ static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_b
         return 0;
 }
 
-int manager_connect_bus(Manager *m) {
-        int r;
+static int on_connected(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
+        Manager *m = userdata;
 
+        assert(message);
         assert(m);
 
-        r = sd_bus_default_system(&m->bus);
-        if (r < 0) {
-                /* We failed to connect? Yuck, we must be in early
-                 * boot. Let's try in 5s again. */
+        /* Did we get a timezone or transient hostname from DHCP while D-Bus wasn't up yet? */
+        if (m->dynamic_hostname)
+                (void) manager_set_hostname(m, m->dynamic_hostname);
+        if (m->dynamic_timezone)
+                (void) manager_set_timezone(m, m->dynamic_timezone);
 
-                log_debug_errno(r, "Failed to connect to bus, trying again in 5s: %m");
+        return 0;
+}
 
-                r = sd_event_add_time(m->event, &m->bus_retry_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + 5*USEC_PER_SEC, 0, on_bus_retry, m);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to install bus reconnect time event: %m");
+int manager_connect_bus(Manager *m) {
+        int r;
+
+        assert(m);
 
+        if (m->bus)
                 return 0;
-        }
 
-        r = sd_bus_match_signal_async(
-                        m->bus, &m->prepare_for_sleep_slot,
-                        "org.freedesktop.login1",
-                        "/org/freedesktop/login1",
-                        "org.freedesktop.login1.Manager",
-                        "PrepareForSleep",
-                        match_prepare_for_sleep, NULL, m);
+        r = bus_open_system_watch_bind(&m->bus);
         if (r < 0)
-                return log_error_errno(r, "Failed to request match for PrepareForSleep: %m");
+                return log_error_errno(r, "Failed to connect to bus: %m");
 
         r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/network1", "org.freedesktop.network1.Manager", manager_vtable, m);
         if (r < 0)
@@ -190,17 +176,27 @@ int manager_connect_bus(Manager *m) {
         if (r < 0)
                 return log_error_errno(r, "Failed to attach bus to event loop: %m");
 
-       /* Did we get a timezone or transient hostname from DHCP while D-Bus wasn't up yet? */
-        if (m->dynamic_hostname) {
-                r = manager_set_hostname(m, m->dynamic_hostname);
-                if (r < 0)
-                        return r;
-        }
-        if (m->dynamic_timezone) {
-                r = manager_set_timezone(m, m->dynamic_timezone);
-                if (r < 0)
-                        return r;
-        }
+        r = sd_bus_match_signal_async(
+                        m->bus,
+                        &m->connected_slot,
+                        "org.freedesktop.DBus.Local",
+                        NULL,
+                        "org.freedesktop.DBus.Local",
+                        "Connected",
+                        on_connected, NULL, m);
+        if (r < 0)
+                return log_error_errno(r, "Failed to request match on Connected signal: %m");
+
+        r = sd_bus_match_signal_async(
+                        m->bus,
+                        &m->prepare_for_sleep_slot,
+                        "org.freedesktop.login1",
+                        "/org/freedesktop/login1",
+                        "org.freedesktop.login1.Manager",
+                        "PrepareForSleep",
+                        match_prepare_for_sleep, NULL, m);
+        if (r < 0)
+                log_warning_errno(r, "Failed to request match for PrepareForSleep, ignoring: %m");
 
         return 0;
 }
@@ -1320,6 +1316,7 @@ void manager_free(Manager *m) {
 
         sd_bus_unref(m->bus);
         sd_bus_slot_unref(m->prepare_for_sleep_slot);
+        sd_bus_slot_unref(m->connected_slot);
         sd_event_source_unref(m->bus_retry_event_source);
 
         free(m->dynamic_timezone);
@@ -1594,12 +1591,12 @@ int manager_set_hostname(Manager *m, const char *hostname) {
         int r;
 
         log_debug("Setting transient hostname: '%s'", strna(hostname));
+
         if (free_and_strdup(&m->dynamic_hostname, hostname) < 0)
                 return log_oom();
 
-        if (!m->bus) {
-                /* TODO: replace by assert when we can rely on kdbus */
-                log_info("Not connected to system bus, ignoring transient hostname.");
+        if (!m->bus || sd_bus_is_ready(m->bus) <= 0) {
+                log_info("Not connected to system bus, not setting hostname.");
                 return 0;
         }
 
@@ -1646,8 +1643,8 @@ int manager_set_timezone(Manager *m, const char *tz) {
         if (free_and_strdup(&m->dynamic_timezone, tz) < 0)
                 return log_oom();
 
-        if (!m->bus) {
-                log_info("Not connected to system bus, ignoring timezone.");
+        if (!m->bus || sd_bus_is_ready(m->bus) <= 0) {
+                log_info("Not connected to system bus, not setting hostname.");
                 return 0;
         }
 
index 186cb418911b3ed033bd766f22d215183f9236a2..1f7f306af9399a35601d583fc2726a9f3dc8282d 100644 (file)
@@ -43,6 +43,7 @@ struct Manager {
         sd_event_source *bus_retry_event_source;
         sd_bus *bus;
         sd_bus_slot *prepare_for_sleep_slot;
+        sd_bus_slot *connected_slot;
         struct udev *udev;
         struct udev_monitor *udev_monitor;
         sd_event_source *udev_event_source;
index ff629ea41b9ebd4a5fb402ef5f9e37dc996a9e37..ffd7c4824e34f6ce9e395b9be2018cff691afd34 100644 (file)
@@ -1844,18 +1844,6 @@ static const sd_bus_vtable resolve_vtable[] = {
         SD_BUS_VTABLE_END,
 };
 
-static int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) {
-        Manager *m = userdata;
-
-        assert(s);
-        assert(m);
-
-        m->bus_retry_event_source = sd_event_source_unref(m->bus_retry_event_source);
-
-        manager_connect_bus(m);
-        return 0;
-}
-
 static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
         Manager *m = userdata;
         int b, r;
@@ -1886,20 +1874,9 @@ int manager_connect_bus(Manager *m) {
         if (m->bus)
                 return 0;
 
-        r = sd_bus_default_system(&m->bus);
-        if (r < 0) {
-                /* We failed to connect? Yuck, we must be in early
-                 * boot. Let's try in 5s again. */
-
-                log_debug_errno(r, "Failed to connect to bus, trying again in 5s: %m");
-
-                r = sd_event_add_time(m->event, &m->bus_retry_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + 5*USEC_PER_SEC, 0, on_bus_retry, m);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to install bus reconnect time event: %m");
-
-                (void) sd_event_source_set_description(m->bus_retry_event_source, "bus-retry");
-                return 0;
-        }
+        r = bus_open_system_watch_bind(&m->bus);
+        if (r < 0)
+                return log_error_errno(r, "Failed to connect to system bus: %m");
 
         r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable, m);
         if (r < 0)
@@ -1940,7 +1917,7 @@ int manager_connect_bus(Manager *m) {
                         NULL,
                         m);
         if (r < 0)
-                log_error_errno(r, "Failed to request match for PrepareForSleep: %m");
+                log_warning_errno(r, "Failed to request match for PrepareForSleep, ignoring: %m");
 
         return 0;
 }
index b9e25a0d4e702e0fcf47fc1a708670b66d612261..b6677e27f609d20af1b3c2e394180d1513a11986 100644 (file)
@@ -1598,3 +1598,54 @@ int bus_track_add_name_many(sd_bus_track *t, char **l) {
 
         return r;
 }
+
+int bus_open_system_watch_bind(sd_bus **ret) {
+        _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
+        const char *e;
+        int r;
+
+        assert(ret);
+
+        /* Match like sd_bus_open_system(), but with the "watch_bind" feature and the Connected() signal turned on. */
+
+        r = sd_bus_new(&bus);
+        if (r < 0)
+                return r;
+
+        e = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
+        if (!e)
+                e = DEFAULT_SYSTEM_BUS_ADDRESS;
+
+        r = sd_bus_set_address(bus, e);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_set_bus_client(bus, true);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_set_trusted(bus, true);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_negotiate_creds(bus, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_set_watch_bind(bus, true);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_set_connected_signal(bus, true);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_start(bus);
+        if (r < 0)
+                return r;
+
+        *ret = bus;
+        bus = NULL;
+
+        return 0;
+}
index a9f4969d7da6ce805a392dac8991ccaa527790b3..cbd22a6cd6b8d46415fc8cbcf33708d37c52ed75 100644 (file)
@@ -162,3 +162,5 @@ int bus_path_decode_unique(const char *path, const char *prefix, char **ret_send
 int bus_property_get_rlimit(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
 
 int bus_track_add_name_many(sd_bus_track *t, char **l);
+
+int bus_open_system_watch_bind(sd_bus **ret);
index 76bd5eff95e08752cfd81ba5c286490d5dc327d7..df21b3f30e61b59a1ae750aab58b842d09039007 100644 (file)
@@ -152,6 +152,8 @@ int sd_bus_set_exit_on_disconnect(sd_bus *bus, int b);
 int sd_bus_get_exit_on_disconnect(sd_bus *bus);
 int sd_bus_set_watch_bind(sd_bus *bus, int b);
 int sd_bus_get_watch_bind(sd_bus *bus);
+int sd_bus_set_connected_signal(sd_bus *bus, int b);
+int sd_bus_get_connected_signal(sd_bus *bus);
 
 int sd_bus_start(sd_bus *bus);