diff --git a/src/core/service.c b/src/core/service.c index 38f8745674..171e091dff 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -4607,6 +4607,11 @@ static int service_get_timeout(Unit *u, usec_t *timeout) { return 1; } +static usec_t service_get_timeout_start_usec(Unit *u) { + Service *s = SERVICE(ASSERT_PTR(u)); + return s->timeout_start_usec; +} + static bool pick_up_pid_from_bus_name(Service *s) { assert(s); @@ -5145,6 +5150,7 @@ const UnitVTable service_vtable = { .bus_commit_properties = bus_service_commit_properties, .get_timeout = service_get_timeout, + .get_timeout_start_usec = service_get_timeout_start_usec, .needs_console = service_needs_console, .exit_status = service_exit_status, .status_text = service_status_text, diff --git a/src/core/unit.c b/src/core/unit.c index 7b2e8c5f5c..570234c8f4 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" @@ -3619,7 +3620,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); @@ -3629,6 +3632,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'," @@ -3636,20 +3645,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; diff --git a/src/core/unit.h b/src/core/unit.h index f2d4fd6a4b..3f1f58d600 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -715,6 +715,9 @@ typedef struct UnitVTable { /* Returns the next timeout of a unit */ int (*get_timeout)(Unit *u, usec_t *timeout); + /* Returns the start timeout of a unit */ + usec_t (*get_timeout_start_usec)(Unit *u); + /* Returns the main PID if there is any defined, or 0. */ pid_t (*main_pid)(Unit *u); diff --git a/src/libsystemd/sd-bus/bus-control.c b/src/libsystemd/sd-bus/bus-control.c index 77b4b5bea6..1355e41ed0 100644 --- a/src/libsystemd/sd-bus/bus-control.c +++ b/src/libsystemd/sd-bus/bus-control.c @@ -876,9 +876,10 @@ _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **r int bus_add_match_internal( sd_bus *bus, const char *match, + uint64_t timeout_usec, uint64_t *ret_counter) { - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; const char *e; int r; @@ -889,16 +890,26 @@ int bus_add_match_internal( e = append_eavesdrop(bus, match); - r = sd_bus_call_method( + r = sd_bus_message_new_method_call( bus, + &m, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", - "AddMatch", + "AddMatch"); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "s", e); + if (r < 0) + return r; + + r = sd_bus_call( + bus, + m, + timeout_usec, NULL, - &reply, - "s", - e); + &reply); if (r < 0) return r; @@ -914,9 +925,12 @@ int bus_add_match_internal_async( sd_bus_slot **ret_slot, const char *match, sd_bus_message_handler_t callback, - void *userdata) { + void *userdata, + uint64_t timeout_usec) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; const char *e; + int r; assert(bus); @@ -925,17 +939,27 @@ int bus_add_match_internal_async( e = append_eavesdrop(bus, match); - return sd_bus_call_method_async( + r = sd_bus_message_new_method_call( bus, - ret_slot, + &m, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", - "AddMatch", + "AddMatch"); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "s", e); + if (r < 0) + return r; + + return sd_bus_call_async( + bus, + ret_slot, + m, callback, userdata, - "s", - e); + timeout_usec); } int bus_remove_match_internal( diff --git a/src/libsystemd/sd-bus/bus-control.h b/src/libsystemd/sd-bus/bus-control.h index 8182b9cd63..1cd4fb88d9 100644 --- a/src/libsystemd/sd-bus/bus-control.h +++ b/src/libsystemd/sd-bus/bus-control.h @@ -3,7 +3,7 @@ #include "sd-bus.h" -int bus_add_match_internal(sd_bus *bus, const char *match, uint64_t *ret_counter); -int bus_add_match_internal_async(sd_bus *bus, sd_bus_slot **ret, const char *match, sd_bus_message_handler_t callback, void *userdata); +int bus_add_match_internal(sd_bus *bus, const char *match, uint64_t timeout_usec, uint64_t *ret_counter); +int bus_add_match_internal_async(sd_bus *bus, sd_bus_slot **ret, const char *match, sd_bus_message_handler_t callback, void *userdata, uint64_t timeout_usec); int bus_remove_match_internal(sd_bus *bus, const char *match); diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h index 1cf6974bff..098a518605 100644 --- a/src/libsystemd/sd-bus/bus-internal.h +++ b/src/libsystemd/sd-bus/bus-internal.h @@ -389,6 +389,16 @@ int bus_attach_inotify_event(sd_bus *b); void bus_close_inotify_fd(sd_bus *b); void bus_close_io_fds(sd_bus *b); +int bus_add_match_full( + sd_bus *bus, + sd_bus_slot **slot, + bool asynchronous, + const char *match, + sd_bus_message_handler_t callback, + sd_bus_message_handler_t install_callback, + void *userdata, + uint64_t timeout_usec); + #define OBJECT_PATH_FOREACH_PREFIX(prefix, path) \ for (char *_slash = ({ strcpy((prefix), (path)); streq((prefix), "/") ? NULL : strrchr((prefix), '/'); }) ; \ _slash && ((_slash[(_slash) == (prefix)] = 0), true); \ diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index 91e7505cd9..d399509816 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -3531,14 +3531,15 @@ static int add_match_callback( return r; } -static int bus_add_match_full( +int bus_add_match_full( sd_bus *bus, sd_bus_slot **slot, bool asynchronous, const char *match, sd_bus_message_handler_t callback, sd_bus_message_handler_t install_callback, - void *userdata) { + void *userdata, + uint64_t timeout_usec) { struct bus_match_component *components = NULL; size_t n_components = 0; @@ -3582,7 +3583,8 @@ static int bus_add_match_full( &s->match_callback.install_slot, s->match_callback.match_string, add_match_callback, - s); + s, + timeout_usec); if (r < 0) return r; @@ -3592,7 +3594,10 @@ static int bus_add_match_full( * then make it floating. */ r = sd_bus_slot_set_floating(s->match_callback.install_slot, true); } else - r = bus_add_match_internal(bus, s->match_callback.match_string, &s->match_callback.after); + r = bus_add_match_internal(bus, + s->match_callback.match_string, + timeout_usec, + &s->match_callback.after); if (r < 0) return r; @@ -3619,7 +3624,7 @@ _public_ int sd_bus_add_match( sd_bus_message_handler_t callback, void *userdata) { - return bus_add_match_full(bus, slot, false, match, callback, NULL, userdata); + return bus_add_match_full(bus, slot, false, match, callback, NULL, userdata, 0); } _public_ int sd_bus_add_match_async( @@ -3630,7 +3635,7 @@ _public_ int sd_bus_add_match_async( sd_bus_message_handler_t install_callback, void *userdata) { - return bus_add_match_full(bus, slot, true, match, callback, install_callback, userdata); + return bus_add_match_full(bus, slot, true, match, callback, install_callback, userdata, 0); } static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {