161 lines
5.9 KiB
Diff
161 lines
5.9 KiB
Diff
From 1daa382a7f9e55d11f7b59b144a9963688169843 Mon Sep 17 00:00:00 2001
|
|
From: Lennart Poettering <lennart@poettering.net>
|
|
Date: Thu, 17 Feb 2022 14:40:25 +0100
|
|
Subject: [PATCH] pid1: lookup owning PID of BusName= name of services
|
|
asynchronously
|
|
|
|
A first step of removing blocking calls to the D-Bus broker from PID 1.
|
|
There's a lot more to got (i.e. grep src/core/ for sd_bus_creds
|
|
basically), but it's a start.
|
|
|
|
Removing blocking calls to D-Bus broker deals systematicallly with
|
|
deadlocks caused by dbus-daemon blocking on synchronous IPC calls back
|
|
to PID1 (e.g. Varlink calls through nss-systemd). Bugs such as #15316.
|
|
|
|
Also-see: https://github.com/systemd/systemd/pull/22038#issuecomment-1042958390
|
|
(cherry picked from commit e39eb045a502d599e6cd3fda7a46020dd438d018)
|
|
(cherry picked from commit cf390149cb25248169c482e315a1a7ff02eaf956)
|
|
|
|
Conflict:NA
|
|
Reference:https://github.com/systemd/systemd/commit/1daa382a7f9e55d11f7b59b144a9963688169843
|
|
---
|
|
src/core/service.c | 91 ++++++++++++++++++++++++++++++++++++----------
|
|
src/core/service.h | 2 +
|
|
2 files changed, 74 insertions(+), 19 deletions(-)
|
|
|
|
diff --git a/src/core/service.c b/src/core/service.c
|
|
index 5f56217904..f6eb46cb54 100644
|
|
--- a/src/core/service.c
|
|
+++ b/src/core/service.c
|
|
@@ -398,6 +398,8 @@ static void service_done(Unit *u) {
|
|
s->timer_event_source = sd_event_source_disable_unref(s->timer_event_source);
|
|
s->exec_fd_event_source = sd_event_source_disable_unref(s->exec_fd_event_source);
|
|
|
|
+ s->bus_name_pid_lookup_slot = sd_bus_slot_unref(s->bus_name_pid_lookup_slot);
|
|
+
|
|
service_release_resources(u);
|
|
}
|
|
|
|
@@ -4216,6 +4218,60 @@ static int service_get_timeout(Unit *u, usec_t *timeout) {
|
|
return 1;
|
|
}
|
|
|
|
+static bool pick_up_pid_from_bus_name(Service *s) {
|
|
+ assert(s);
|
|
+
|
|
+ /* If the service is running but we have no main PID yet, get it from the owner of the D-Bus name */
|
|
+
|
|
+ return !pid_is_valid(s->main_pid) &&
|
|
+ IN_SET(s->state,
|
|
+ SERVICE_START,
|
|
+ SERVICE_START_POST,
|
|
+ SERVICE_RUNNING,
|
|
+ SERVICE_RELOAD);
|
|
+}
|
|
+
|
|
+static int bus_name_pid_lookup_callback(sd_bus_message *reply, void *userdata, sd_bus_error *ret_error) {
|
|
+ const sd_bus_error *e;
|
|
+ Unit *u = userdata;
|
|
+ uint32_t pid;
|
|
+ Service *s;
|
|
+ int r;
|
|
+
|
|
+ assert(reply);
|
|
+ assert(u);
|
|
+
|
|
+ s = SERVICE(u);
|
|
+ s->bus_name_pid_lookup_slot = sd_bus_slot_unref(s->bus_name_pid_lookup_slot);
|
|
+
|
|
+ if (!s->bus_name || !pick_up_pid_from_bus_name(s))
|
|
+ return 1;
|
|
+
|
|
+ e = sd_bus_message_get_error(reply);
|
|
+ if (e) {
|
|
+ r = sd_bus_error_get_errno(e);
|
|
+ log_warning_errno(r, "GetConnectionUnixProcessID() failed: %s", bus_error_message(e, r));
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ r = sd_bus_message_read(reply, "u", &pid);
|
|
+ if (r < 0) {
|
|
+ bus_log_parse_error(r);
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ if (!pid_is_valid(pid)) {
|
|
+ log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "GetConnectionUnixProcessID() returned invalid PID");
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ log_unit_debug(u, "D-Bus name %s is now owned by process " PID_FMT, s->bus_name, (pid_t) pid);
|
|
+
|
|
+ service_set_main_pid(s, pid);
|
|
+ unit_watch_pid(UNIT(s), pid, false);
|
|
+ return 1;
|
|
+}
|
|
+
|
|
static void service_bus_name_owner_change(Unit *u, const char *new_owner) {
|
|
|
|
Service *s = SERVICE(u);
|
|
@@ -4246,28 +4302,25 @@ static void service_bus_name_owner_change(Unit *u, const char *new_owner) {
|
|
else if (s->state == SERVICE_START && new_owner)
|
|
service_enter_start_post(s);
|
|
|
|
- } else if (new_owner &&
|
|
- s->main_pid <= 0 &&
|
|
- IN_SET(s->state,
|
|
- SERVICE_START,
|
|
- SERVICE_START_POST,
|
|
- SERVICE_RUNNING,
|
|
- SERVICE_RELOAD)) {
|
|
-
|
|
- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
|
|
- pid_t pid;
|
|
+ } else if (new_owner && pick_up_pid_from_bus_name(s)) {
|
|
|
|
/* Try to acquire PID from bus service */
|
|
|
|
- r = sd_bus_get_name_creds(u->manager->api_bus, s->bus_name, SD_BUS_CREDS_PID, &creds);
|
|
- if (r >= 0)
|
|
- r = sd_bus_creds_get_pid(creds, &pid);
|
|
- if (r >= 0) {
|
|
- log_unit_debug(u, "D-Bus name %s is now owned by process " PID_FMT, s->bus_name, pid);
|
|
-
|
|
- service_set_main_pid(s, pid);
|
|
- unit_watch_pid(UNIT(s), pid, false);
|
|
- }
|
|
+ s->bus_name_pid_lookup_slot = sd_bus_slot_unref(s->bus_name_pid_lookup_slot);
|
|
+
|
|
+ r = sd_bus_call_method_async(
|
|
+ u->manager->api_bus,
|
|
+ &s->bus_name_pid_lookup_slot,
|
|
+ "org.freedesktop.DBus",
|
|
+ "/org/freedesktop/DBus",
|
|
+ "org.freedesktop.DBus",
|
|
+ "GetConnectionUnixProcessID",
|
|
+ bus_name_pid_lookup_callback,
|
|
+ s,
|
|
+ "s",
|
|
+ s->bus_name);
|
|
+ if (r < 0)
|
|
+ log_debug_errno(r, "Failed to request owner PID of service name, ignoring: %m");
|
|
}
|
|
}
|
|
|
|
diff --git a/src/core/service.h b/src/core/service.h
|
|
index 6d931c3d5e..6c47c91f85 100644
|
|
--- a/src/core/service.h
|
|
+++ b/src/core/service.h
|
|
@@ -185,6 +185,8 @@ struct Service {
|
|
NotifyAccess notify_access;
|
|
NotifyState notify_state;
|
|
|
|
+ sd_bus_slot *bus_name_pid_lookup_slot;
|
|
+
|
|
sd_event_source *exec_fd_event_source;
|
|
|
|
ServiceFDStore *fd_store;
|
|
--
|
|
2.33.0
|
|
|