summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2017-12-19 15:54:30 +0100
committerLennart Poettering <lennart@poettering.net>2018-01-05 13:58:32 +0100
commitd7afd945b5aad5b262a3de97614f486d63d94612 (patch)
tree43ffeba1b997d2b9e99dab4b5ece7b9ae5b54ce2
parentb38cc8d5631253738d5474f39b2026eb5524f772 (diff)
downloadsystemd-d7afd945b5aad5b262a3de97614f486d63d94612.tar.gz
networkd,resolved: make use of watch_bind feature to connect to the bus
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.
-rw-r--r--src/network/networkd-manager.c93
-rw-r--r--src/network/networkd-manager.h1
-rw-r--r--src/resolve/resolved-bus.c31
-rw-r--r--src/shared/bus-util.c51
-rw-r--r--src/shared/bus-util.h2
-rw-r--r--src/systemd/sd-bus.h2
6 files changed, 105 insertions, 75 deletions
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index 79d58dd099..4733dd5177 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -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;
}
diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h
index 186cb41891..1f7f306af9 100644
--- a/src/network/networkd-manager.h
+++ b/src/network/networkd-manager.h
@@ -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;
diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c
index ff629ea41b..ffd7c4824e 100644
--- a/src/resolve/resolved-bus.c
+++ b/src/resolve/resolved-bus.c
@@ -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;
}
diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c
index b9e25a0d4e..b6677e27f6 100644
--- a/src/shared/bus-util.c
+++ b/src/shared/bus-util.c
@@ -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;
+}
diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h
index a9f4969d7d..cbd22a6cd6 100644
--- a/src/shared/bus-util.h
+++ b/src/shared/bus-util.h
@@ -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);
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
index 76bd5eff95..df21b3f30e 100644
--- a/src/systemd/sd-bus.h
+++ b/src/systemd/sd-bus.h
@@ -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);