core: ensure varlink Unit.List() can query inactive units

manager_get_unit() only returns loaded units, if a unit is
stopped and not referenced by anything it will be GCed, so
this method will return nothing. Use manager_load_unit()
instead so that a stopped unit gets loaded and we can
return its state to the caller, after checking that it
actually exists.

Follow-up for d2a8dbabf5
This commit is contained in:
Luca Boccassi
2026-02-13 19:16:13 +00:00
parent b5f8725989
commit cb7c0950b3
2 changed files with 43 additions and 3 deletions
+37 -3
View File
@@ -361,6 +361,40 @@ static int lookup_unit_by_pidref(sd_varlink *link, Manager *manager, PidRef *pid
return 0;
}
static int load_unit_and_check(sd_varlink *link, Manager *manager, const char *name, Unit **ret_unit) {
Unit *unit;
int r;
assert(link);
assert(manager);
assert(name);
assert(ret_unit);
r = manager_load_unit(manager, name, /* path= */ NULL, /* e= */ NULL, &unit);
if (r < 0)
return r;
/* manager_load_unit() will create an object regardless of whether the unit actually exists, so
* check the state and refuse if it's not in a good state. */
if (IN_SET(unit->load_state, UNIT_NOT_FOUND, UNIT_STUB, UNIT_MERGED))
return sd_varlink_error(link, "io.systemd.Unit.NoSuchUnit", NULL);
if (unit->load_state == UNIT_BAD_SETTING)
return sd_varlink_error(link, "io.systemd.Unit.UnitError", NULL);
if (unit->load_state == UNIT_ERROR)
return sd_varlink_errorbo(
link,
SD_VARLINK_ERROR_SYSTEM,
SD_JSON_BUILD_PAIR_STRING("origin", "linux"),
SD_JSON_BUILD_PAIR_INTEGER("errno", unit->load_error),
JSON_BUILD_PAIR_STRING_NON_EMPTY("errnoName", "io.systemd.Unit.UnitError"));
if (unit->load_state == UNIT_MASKED)
return sd_varlink_error(link, "io.systemd.Unit.UnitMasked", NULL);
assert(UNIT_IS_LOAD_COMPLETE(unit->load_state));
*ret_unit = unit;
return 0;
}
typedef struct UnitLookupParameters {
const char *name, *cgroup;
PidRef pidref;
@@ -400,9 +434,9 @@ static int lookup_unit_by_parameters(
assert(ret);
if (p->name) {
unit = manager_get_unit(manager, p->name);
if (!unit)
return varlink_error_no_such_unit(link, "name");
r = load_unit_and_check(link, manager, p->name, &unit);
if (r < 0)
return r;
}
if (pidref_is_set_or_automatic(&p->pidref)) {
+6
View File
@@ -1025,6 +1025,8 @@ static SD_VARLINK_DEFINE_ERROR(
static SD_VARLINK_DEFINE_ERROR(OnlyByDependency);
static SD_VARLINK_DEFINE_ERROR(DBusShuttingDown);
static SD_VARLINK_DEFINE_ERROR(UnitMasked);
static SD_VARLINK_DEFINE_ERROR(UnitError);
SD_VARLINK_DEFINE_INTERFACE(
io_systemd_Unit,
@@ -1091,6 +1093,10 @@ SD_VARLINK_DEFINE_INTERFACE(
/* Errors */
SD_VARLINK_SYMBOL_COMMENT("No matching unit found"),
&vl_error_NoSuchUnit,
SD_VARLINK_SYMBOL_COMMENT("The unit is masked"),
&vl_error_UnitMasked,
SD_VARLINK_SYMBOL_COMMENT("Unit is in a fatal error state"),
&vl_error_UnitError,
SD_VARLINK_SYMBOL_COMMENT("Job for the unit may only be enqueued by dependencies"),
&vl_error_OnlyByDependency,
SD_VARLINK_SYMBOL_COMMENT("A unit that requires D-Bus cannot be started as D-Bus is shutting down"),