From d027b6a74262c7278a3af8dd5c56b71da256daf4 Mon Sep 17 00:00:00 2001 From: licunlong Date: Wed, 24 May 2023 11:45:31 +0800 Subject: [PATCH] core/unit: increase the NameOwnerChanged/GetNameOwner timeout to the unit's start timeout When dbus is overloaded, these messages are easily timedout, systemd may kill dbus-type service by mistake. This PR mitigates this problem by increasing the timeout to the unit's start timeout. (cherry picked from commit 8df433d7cd268ae96cfe795feaa59f4d3e87b85c) Related: RHEL-111629 --- src/core/unit.c | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/src/core/unit.c b/src/core/unit.c index d98ecf4367..6bf7296154 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -14,6 +14,7 @@ #include "bpf-foreign.h" #include "bpf-socket-bind.h" #include "bus-common-errors.h" +#include "bus-internal.h" #include "bus-util.h" #include "cgroup-setup.h" #include "cgroup-util.h" @@ -3518,7 +3519,9 @@ static int get_name_owner_handler(sd_bus_message *message, void *userdata, sd_bu } int unit_install_bus_match(Unit *u, sd_bus *bus, const char *name) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; const char *match; + usec_t timeout_usec = 0; int r; assert(u); @@ -3528,6 +3531,12 @@ int unit_install_bus_match(Unit *u, sd_bus *bus, const char *name) { if (u->match_bus_slot || u->get_name_owner_slot) return -EBUSY; + /* NameOwnerChanged and GetNameOwner is used to detect when a service finished starting up. The dbus + * call timeout shouldn't be earlier than that. If we couldn't get the start timeout, use the default + * value defined above. */ + if (UNIT_VTABLE(u)->get_timeout_start_usec) + timeout_usec = UNIT_VTABLE(u)->get_timeout_start_usec(u); + match = strjoina("type='signal'," "sender='org.freedesktop.DBus'," "path='/org/freedesktop/DBus'," @@ -3535,20 +3544,40 @@ int unit_install_bus_match(Unit *u, sd_bus *bus, const char *name) { "member='NameOwnerChanged'," "arg0='", name, "'"); - r = sd_bus_add_match_async(bus, &u->match_bus_slot, match, signal_name_owner_changed, NULL, u); + r = bus_add_match_full( + bus, + &u->match_bus_slot, + true, + match, + signal_name_owner_changed, + NULL, + u, + timeout_usec); if (r < 0) return r; - r = sd_bus_call_method_async( + r = sd_bus_message_new_method_call( bus, - &u->get_name_owner_slot, + &m, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", - "GetNameOwner", + "GetNameOwner"); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "s", name); + if (r < 0) + return r; + + r = sd_bus_call_async( + bus, + &u->get_name_owner_slot, + m, get_name_owner_handler, u, - "s", name); + timeout_usec); + if (r < 0) { u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot); return r;