diff --git a/src/systemctl/systemctl-start-unit.c b/src/systemctl/systemctl-start-unit.c index 8268217967b..c6b4433aa01 100644 --- a/src/systemctl/systemctl-start-unit.c +++ b/src/systemctl/systemctl-start-unit.c @@ -392,8 +392,8 @@ int verb_start(int argc, char *argv[], void *userdata) { /* When stopping units, warn if they can still be triggered by * another active unit (socket, path, timer) */ if (!arg_quiet) - STRV_FOREACH(name, stopped_units) - (void) check_triggering_units(bus, *name); + STRV_FOREACH(unit, stopped_units) + warn_triggering_units(bus, *unit, "Stopping", /* ignore_masked = */ true); } if (arg_wait) { diff --git a/src/systemctl/systemctl-util.c b/src/systemctl/systemctl-util.c index 10df0087b44..2498725d3f4 100644 --- a/src/systemctl/systemctl-util.c +++ b/src/systemctl/systemctl-util.c @@ -315,26 +315,33 @@ int expand_unit_names(sd_bus *bus, char **names, const char* suffix, char ***ret return 0; } -int check_triggering_units(sd_bus *bus, const char *unit) { +int get_active_triggering_units(sd_bus *bus, const char *unit, bool ignore_masked, char ***ret) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_free_ char *n = NULL, *dbus_path = NULL, *load_state = NULL; - _cleanup_strv_free_ char **triggered_by = NULL; + _cleanup_strv_free_ char **triggered_by = NULL, **active = NULL; + _cleanup_free_ char *name = NULL, *dbus_path = NULL; int r; - r = unit_name_mangle(unit, 0, &n); - if (r < 0) - return log_error_errno(r, "Failed to mangle unit name: %m"); + assert(bus); + assert(unit); + assert(ret); - r = unit_load_state(bus, n, &load_state); + r = unit_name_mangle(unit, 0, &name); if (r < 0) return r; - if (streq(load_state, "masked")) - return 0; + if (ignore_masked) { + r = unit_is_masked(bus, name); + if (r < 0) + return r; + if (r > 0) { + *ret = NULL; + return 0; + } + } - dbus_path = unit_dbus_path_from_name(n); + dbus_path = unit_dbus_path_from_name(name); if (!dbus_path) - return log_oom(); + return -ENOMEM; r = sd_bus_get_property_strv( bus, @@ -345,9 +352,9 @@ int check_triggering_units(sd_bus *bus, const char *unit) { &error, &triggered_by); if (r < 0) - return log_error_errno(r, "Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r)); + return log_debug_errno(r, "Failed to get TriggeredBy property of unit '%s': %s", + name, bus_error_message(&error, r)); - bool first = true; STRV_FOREACH(i, triggered_by) { UnitActiveState active_state; @@ -358,17 +365,43 @@ int check_triggering_units(sd_bus *bus, const char *unit) { if (!IN_SET(active_state, UNIT_ACTIVE, UNIT_RELOADING)) continue; - if (first) { - log_warning("Warning: Stopping %s, but it can still be activated by:", n); - first = false; - } - - log_warning(" %s", *i); + r = strv_extend(&active, *i); + if (r < 0) + return r; } + *ret = TAKE_PTR(active); return 0; } +void warn_triggering_units(sd_bus *bus, const char *unit, const char *operation, bool ignore_masked) { + _cleanup_strv_free_ char **triggered_by = NULL; + _cleanup_free_ char *joined = NULL; + int r; + + assert(bus); + assert(unit); + assert(operation); + + r = get_active_triggering_units(bus, unit, ignore_masked, &triggered_by); + if (r < 0) { + log_warning_errno(r, + "Failed to get triggering units for '%s', ignoring: %m", unit); + return; + } + + if (strv_isempty(triggered_by)) + return; + + joined = strv_join(triggered_by, ", "); + if (!joined) + return (void) log_oom(); + + log_warning("%s '%s', but its triggering units are still active:\n" + "%s", + operation, unit, joined); +} + int need_daemon_reload(sd_bus *bus, const char *unit) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; const char *path; diff --git a/src/systemctl/systemctl-util.h b/src/systemctl/systemctl-util.h index 344075722ad..7bddef07ef4 100644 --- a/src/systemctl/systemctl-util.h +++ b/src/systemctl/systemctl-util.h @@ -26,7 +26,8 @@ int get_sub_state_one_unit(sd_bus *bus, const char *unit, char **ret_sub_state); int get_unit_list(sd_bus *bus, const char *machine, char **patterns, UnitInfo **unit_infos, int c, sd_bus_message **ret_reply); int expand_unit_names(sd_bus *bus, char **names, const char* suffix, char ***ret, bool *ret_expanded); -int check_triggering_units(sd_bus *bus, const char *unit); +int get_active_triggering_units(sd_bus *bus, const char *unit, bool ignore_masked, char ***ret); +void warn_triggering_units(sd_bus *bus, const char *unit, const char *operation, bool ignore_masked); int need_daemon_reload(sd_bus *bus, const char *unit);