1
0
mirror of https://github.com/systemd/systemd synced 2026-04-03 21:54:58 +02:00

Compare commits

..

No commits in common. "3663f754f1dab56c5860d91e42983d30243d0617" and "aedec452b9e5dd197881f2164fb205dfe8bfdcec" have entirely different histories.

19 changed files with 107 additions and 182 deletions

View File

@ -99,8 +99,8 @@
<term><option>set-default</option> <replaceable>ID</replaceable></term>
<term><option>set-oneshot</option> <replaceable>ID</replaceable></term>
<listitem><para>Sets the default boot loader entry. Takes a single boot loader entry ID string or a glob
pattern as argument. The <option>set-oneshot</option> command will set the default entry only for the next boot,
<listitem><para>Sets the default boot loader entry. Takes a single boot loader entry ID string as
argument. The <option>set-oneshot</option> command will set the default entry only for the next boot,
the <option>set-default</option> will set it persistently for all future boots.</para></listitem>
<listitem><para>Optionally, the boot loader entry ID may be specified as one of: <option>@default</option>,
@ -111,12 +111,8 @@
see <ulink url="https://systemd.io/BOOT_LOADER_SPECIFICATION">Boot Loader Specification</ulink> for details.
These special IDs are primarily useful as a quick way to persistently make the currently booted boot loader
entry the default choice, or to upgrade the default boot loader entry for the next boot to the default boot
loader entry for all future boots, but may be used for other operations too.</para>
<para>If set to <option>@saved</option> the chosen entry will be saved as an EFI variable
on every boot and automatically selected the next time the boot loader starts.</para>
<para>When an empty string ("") is specified as an ID, then the corresponding EFI variable will be unset.
loader entry for all future boots, but may be used for other operations too.
When an empty string ("") is specified as an ID, then the corresponding EFI variable will be unset.
</para></listitem>
</varlistentry>

View File

@ -60,9 +60,6 @@
selected entry will be stored as an EFI variable, overriding this option.
</para>
<para>If set to <literal>@saved</literal> the chosen entry will be saved as an EFI variable
on every boot and automatically selected the next time the boot loader starts.</para>
<table>
<title>Automatically detected entries will use the following names:</title>

View File

@ -72,4 +72,3 @@ Packages=
strace
tpm2-tss
less
netcat

View File

@ -1834,7 +1834,7 @@ static int parse_loader_entry_target_arg(const char *arg1, char16_t **ret_target
if (r < 0)
return log_error_errno(r, "Failed to get EFI variable 'LoaderEntryDefault': %m");
} else if (arg1[0] == '@' && !streq(arg1, "@saved"))
} else if (arg1[0] == '@')
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unsupported special entry identifier: %s", arg1);
else {
encoded = utf8_to_utf16(arg1, strlen(arg1));

View File

@ -67,17 +67,13 @@ typedef struct {
UINT32 timeout_sec; /* Actual timeout used (efi_main() override > efivar > config). */
UINT32 timeout_sec_config;
UINT32 timeout_sec_efivar;
CHAR16 *entry_default_config;
CHAR16 *entry_default_efivar;
CHAR16 *entry_default_pattern;
CHAR16 *entry_oneshot;
CHAR16 *entry_saved;
CHAR16 *options_edit;
BOOLEAN editor;
BOOLEAN auto_entries;
BOOLEAN auto_firmware;
BOOLEAN force_menu;
BOOLEAN use_saved_entry;
BOOLEAN use_saved_entry_efivar;
INT64 console_mode;
INT64 console_mode_efivar;
RandomSeedMode random_seed_mode;
@ -439,7 +435,7 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) {
UINT64 key;
UINTN x_max, y_max;
SecureBootMode secure;
_cleanup_freepool_ CHAR16 *device_part_uuid = NULL;
_cleanup_freepool_ CHAR16 *device_part_uuid = NULL, *default_efivar = NULL;
assert(config);
assert(loaded_image_path);
@ -449,6 +445,7 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) {
secure = secure_boot_mode();
(void) efivar_get(LOADER_GUID, L"LoaderDevicePartUUID", &device_part_uuid);
(void) efivar_get(LOADER_GUID, L"LoaderEntryDefault", &default_efivar);
/* We employ some unusual indentation here for readability. */
@ -489,10 +486,9 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) {
Print(L" timeout (EFI var): %lu s\n", config->timeout_sec_efivar);
}
ps_string(L" default: %s\n", config->entry_default_config);
ps_string(L" default (EFI var): %s\n", config->entry_default_efivar);
ps_string(L" default: %s\n", config->entry_default_pattern);
ps_string(L" default (one-shot): %s\n", config->entry_oneshot);
ps_string(L" saved entry: %s\n", config->entry_saved);
ps_string(L" default (EFI var): %s\n", default_efivar);
ps_bool(L" editor: %s\n", config->editor);
ps_bool(L" auto-entries: %s\n", config->auto_entries);
ps_bool(L" auto-firmware: %s\n", config->auto_firmware);
@ -590,7 +586,6 @@ static BOOLEAN menu_run(
INT16 idx;
BOOLEAN exit = FALSE, run = TRUE, firmware_setup = FALSE;
INT64 console_mode_initial = ST->ConOut->Mode->Mode, console_mode_efivar_saved = config->console_mode_efivar;
INTN default_efivar_saved = config->idx_default_efivar;
graphics_mode(FALSE);
ST->ConIn->Reset(ST->ConIn, FALSE);
@ -836,20 +831,20 @@ static BOOLEAN menu_run(
case KEYPRESS(0, 0, 'd'):
case KEYPRESS(0, 0, 'D'):
if (config->idx_default_efivar != (INTN)idx_highlight) {
FreePool(config->entry_default_efivar);
config->entry_default_efivar = StrDuplicate(config->entries[idx_highlight]->id);
if (!config->entry_default_efivar) {
log_oom();
return FALSE;
}
/* store the selected entry in a persistent EFI variable */
efivar_set(
LOADER_GUID,
L"LoaderEntryDefault",
config->entries[idx_highlight]->id,
EFI_VARIABLE_NON_VOLATILE);
config->idx_default_efivar = idx_highlight;
status = StrDuplicate(L"Default boot entry selected.");
} else {
config->entry_default_efivar = mfree(config->entry_default_efivar);
/* clear the default entry EFI variable */
efivar_set(LOADER_GUID, L"LoaderEntryDefault", NULL, EFI_VARIABLE_NON_VOLATILE);
config->idx_default_efivar = -1;
status = StrDuplicate(L"Default boot entry cleared.");
}
config->use_saved_entry_efivar = FALSE;
refresh = TRUE;
break;
@ -959,9 +954,6 @@ static BOOLEAN menu_run(
/* Update EFI vars after we left the menu to reduce NVRAM writes. */
if (default_efivar_saved != config->idx_default_efivar)
efivar_set(LOADER_GUID, L"LoaderEntryDefault", config->entry_default_efivar, EFI_VARIABLE_NON_VOLATILE);
if (console_mode_efivar_saved != config->console_mode_efivar) {
if (config->console_mode_efivar == CONSOLE_MODE_KEEP)
efivar_set(LOADER_GUID, L"LoaderConfigConsoleMode", NULL, EFI_VARIABLE_NON_VOLATILE);
@ -1117,12 +1109,9 @@ static void config_defaults_load_from_file(Config *config, CHAR8 *content) {
}
if (strcmpa((CHAR8 *)"default", key) == 0) {
if (value[0] == '@' && strcmpa((CHAR8 *)"@saved", value) != 0) {
log_error_stall(L"Unsupported special entry identifier: %a", value);
continue;
}
FreePool(config->entry_default_config);
config->entry_default_config = stra_to_str(value);
FreePool(config->entry_default_pattern);
config->entry_default_pattern = stra_to_str(value);
StrLwr(config->entry_default_pattern);
continue;
}
@ -1548,18 +1537,6 @@ static void config_load_defaults(Config *config, EFI_FILE *root_dir) {
err = efivar_get_uint_string(LOADER_GUID, L"LoaderConfigConsoleMode", &value);
if (!EFI_ERROR(err))
config->console_mode_efivar = value;
err = efivar_get(LOADER_GUID, L"LoaderEntryOneShot", &config->entry_oneshot);
if (!EFI_ERROR(err))
/* Unset variable now, after all it's "one shot". */
(void) efivar_set(LOADER_GUID, L"LoaderEntryOneShot", NULL, EFI_VARIABLE_NON_VOLATILE);
(void) efivar_get(LOADER_GUID, L"LoaderEntryDefault", &config->entry_default_efivar);
config->use_saved_entry = streq_ptr(config->entry_default_config, L"@saved");
config->use_saved_entry_efivar = streq_ptr(config->entry_default_efivar, L"@saved");
if (config->use_saved_entry || config->use_saved_entry_efivar)
(void) efivar_get(LOADER_GUID, L"LoaderEntryLastBooted", &config->entry_saved);
}
static void config_load_entries(
@ -1645,45 +1622,69 @@ static void config_sort_entries(Config *config) {
sort_pointer_array((void**) config->entries, config->entry_count, (compare_pointer_func_t) config_entry_compare);
}
static INTN config_entry_find(Config *config, CHAR16 *needle) {
static INTN config_entry_find(Config *config, CHAR16 *id) {
assert(config);
if (!needle)
return -1;
assert(id);
for (UINTN i = 0; i < config->entry_count; i++)
if (MetaiMatch(config->entries[i]->id, needle))
if (StrCmp(config->entries[i]->id, id) == 0)
return (INTN) i;
return -1;
}
static void config_default_entry_select(Config *config) {
_cleanup_freepool_ CHAR16 *entry_default = NULL;
EFI_STATUS err;
INTN i;
assert(config);
i = config_entry_find(config, config->entry_oneshot);
if (i >= 0) {
config->idx_default = i;
return;
/*
* The EFI variable to specify a boot entry for the next, and only the
* next reboot. The variable is always cleared directly after it is read.
*/
err = efivar_get(LOADER_GUID, L"LoaderEntryOneShot", &config->entry_oneshot);
if (!EFI_ERROR(err)) {
efivar_set(LOADER_GUID, L"LoaderEntryOneShot", NULL, EFI_VARIABLE_NON_VOLATILE);
i = config_entry_find(config, config->entry_oneshot);
if (i >= 0) {
config->idx_default = i;
return;
}
}
i = config_entry_find(config, config->use_saved_entry_efivar ? config->entry_saved : config->entry_default_efivar);
if (i >= 0) {
config->idx_default = i;
config->idx_default_efivar = i;
return;
/*
* The EFI variable to select the default boot entry overrides the
* configured pattern. The variable can be set and cleared by pressing
* the 'd' key in the loader selection menu.
*/
err = efivar_get(LOADER_GUID, L"LoaderEntryDefault", &entry_default);
if (!EFI_ERROR(err)) {
i = config_entry_find(config, entry_default);
if (i >= 0) {
config->idx_default = i;
config->idx_default_efivar = i;
return;
}
}
if (config->use_saved_entry)
/* No need to do the same thing twice. */
i = config->use_saved_entry_efivar ? -1 : config_entry_find(config, config->entry_saved);
else
i = config_entry_find(config, config->entry_default_config);
if (i >= 0) {
config->idx_default = i;
if (config->entry_count == 0)
return;
/*
* Match the pattern from the end of the list to the start, find last
* entry (largest number) matching the given pattern.
*/
if (config->entry_default_pattern) {
i = config->entry_count;
while (i--) {
if (MetaiMatch(config->entries[i]->id, config->entry_default_pattern)) {
config->idx_default = i;
return;
}
}
}
/* select the last suitable entry */
@ -2223,7 +2224,7 @@ static void config_free(Config *config) {
for (UINTN i = 0; i < config->entry_count; i++)
config_entry_free(config->entries[i]);
FreePool(config->entries);
FreePool(config->entry_default_config);
FreePool(config->entry_default_pattern);
FreePool(config->options_edit);
FreePool(config->entry_oneshot);
}
@ -2255,29 +2256,6 @@ static void config_write_entries_to_variable(Config *config) {
(void) efivar_set_raw(LOADER_GUID, L"LoaderEntries", buffer, sz, 0);
}
static void save_selected_entry(const Config *config, const ConfigEntry *entry) {
assert(config);
assert(entry);
assert(!entry->call);
/* Always export the selected boot entry to the system in a volatile var. */
(void) efivar_set(LOADER_GUID, L"LoaderEntrySelected", entry->id, 0);
/* Do not save or delete if this was a oneshot boot. */
if (streq_ptr(config->entry_oneshot, entry->id))
return;
if (config->use_saved_entry_efivar || (!config->entry_default_efivar && config->use_saved_entry)) {
/* Avoid unnecessary NVRAM writes. */
if (streq_ptr(config->entry_saved, entry->id))
return;
(void) efivar_set(LOADER_GUID, L"LoaderEntryLastBooted", entry->id, EFI_VARIABLE_NON_VOLATILE);
} else
/* Delete the non-volatile var if not needed. */
(void) efivar_set(LOADER_GUID, L"LoaderEntryLastBooted", NULL, EFI_VARIABLE_NON_VOLATILE);
}
static void export_variables(
EFI_LOADED_IMAGE *loaded_image,
const CHAR16 *loaded_image_path,
@ -2456,7 +2434,9 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
}
config_entry_bump_counters(entry, root_dir);
save_selected_entry(&config, entry);
/* Export the selected boot entry to the system */
(void) efivar_set(LOADER_GUID, L"LoaderEntrySelected", entry->id, 0);
/* Optionally, read a random seed off the ESP and pass it to the OS */
(void) process_random_seed(root_dir, config.random_seed_mode);

View File

@ -786,11 +786,6 @@ static void automount_enter_running(Automount *a) {
goto fail;
}
if (unit_has_failed_condition_or_assert(trigger)) {
automount_enter_dead(a, AUTOMOUNT_FAILURE_MOUNT_CONDITION_FAILED);
return;
}
r = manager_add_job(UNIT(a)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, NULL);
if (r < 0) {
log_unit_warning(UNIT(a), "Failed to queue mount startup job: %s", bus_error_message(&error, r));
@ -1079,12 +1074,11 @@ static int automount_test_start_limit(Unit *u) {
}
static const char* const automount_result_table[_AUTOMOUNT_RESULT_MAX] = {
[AUTOMOUNT_SUCCESS] = "success",
[AUTOMOUNT_FAILURE_RESOURCES] = "resources",
[AUTOMOUNT_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
[AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT] = "mount-start-limit-hit",
[AUTOMOUNT_FAILURE_UNMOUNTED] = "unmounted",
[AUTOMOUNT_FAILURE_MOUNT_CONDITION_FAILED] = "mount-condition-failed",
[AUTOMOUNT_SUCCESS] = "success",
[AUTOMOUNT_FAILURE_RESOURCES] = "resources",
[AUTOMOUNT_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
[AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT] = "mount-start-limit-hit",
[AUTOMOUNT_FAILURE_UNMOUNTED] = "unmounted",
};
DEFINE_STRING_TABLE_LOOKUP(automount_result, AutomountResult);

View File

@ -11,7 +11,6 @@ typedef enum AutomountResult {
AUTOMOUNT_FAILURE_UNMOUNTED,
AUTOMOUNT_FAILURE_START_LIMIT_HIT,
AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT,
AUTOMOUNT_FAILURE_MOUNT_CONDITION_FAILED,
_AUTOMOUNT_RESULT_MAX,
_AUTOMOUNT_RESULT_INVALID = -EINVAL,
} AutomountResult;

View File

@ -480,7 +480,7 @@ static void path_enter_dead(Path *p, PathResult f) {
p->result = f;
unit_log_result(UNIT(p), p->result == PATH_SUCCESS, path_result_to_string(p->result));
path_set_state(p, p->result == PATH_SUCCESS ? PATH_DEAD : PATH_FAILED);
path_set_state(p, p->result != PATH_SUCCESS ? PATH_FAILED : PATH_DEAD);
}
static void path_enter_running(Path *p) {
@ -780,11 +780,6 @@ static void path_trigger_notify(Unit *u, Unit *other) {
return;
}
if (unit_has_failed_condition_or_assert(other)) {
path_enter_dead(p, PATH_FAILURE_UNIT_CONDITION_FAILED);
return;
}
/* Don't propagate anything if there's still a job queued */
if (other->job)
return;
@ -837,11 +832,10 @@ static const char* const path_type_table[_PATH_TYPE_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(path_type, PathType);
static const char* const path_result_table[_PATH_RESULT_MAX] = {
[PATH_SUCCESS] = "success",
[PATH_FAILURE_RESOURCES] = "resources",
[PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
[PATH_FAILURE_UNIT_START_LIMIT_HIT] = "unit-start-limit-hit",
[PATH_FAILURE_UNIT_CONDITION_FAILED] = "unit-condition-failed",
[PATH_SUCCESS] = "success",
[PATH_FAILURE_RESOURCES] = "resources",
[PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
[PATH_FAILURE_UNIT_START_LIMIT_HIT] = "unit-start-limit-hit",
};
DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult);

View File

@ -46,7 +46,6 @@ typedef enum PathResult {
PATH_FAILURE_RESOURCES,
PATH_FAILURE_START_LIMIT_HIT,
PATH_FAILURE_UNIT_START_LIMIT_HIT,
PATH_FAILURE_UNIT_CONDITION_FAILED,
_PATH_RESULT_MAX,
_PATH_RESULT_INVALID = -EINVAL,
} PathResult;

View File

@ -2335,15 +2335,6 @@ static void socket_enter_running(Socket *s, int cfd_in) {
goto refuse;
}
if (UNIT_ISSET(s->service) && cfd < 0) {
Unit *service = UNIT_DEREF(s->service);
if (unit_has_failed_condition_or_assert(service)) {
socket_enter_dead(s, SOCKET_FAILURE_SERVICE_CONDITION_FAILED);
return;
}
}
if (cfd < 0) {
bool pending = false;
Unit *other;
@ -3453,16 +3444,15 @@ static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(socket_exec_command, SocketExecCommand);
static const char* const socket_result_table[_SOCKET_RESULT_MAX] = {
[SOCKET_SUCCESS] = "success",
[SOCKET_FAILURE_RESOURCES] = "resources",
[SOCKET_FAILURE_TIMEOUT] = "timeout",
[SOCKET_FAILURE_EXIT_CODE] = "exit-code",
[SOCKET_FAILURE_SIGNAL] = "signal",
[SOCKET_FAILURE_CORE_DUMP] = "core-dump",
[SOCKET_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
[SOCKET_FAILURE_TRIGGER_LIMIT_HIT] = "trigger-limit-hit",
[SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit",
[SOCKET_FAILURE_SERVICE_CONDITION_FAILED] = "service-condition-failed",
[SOCKET_SUCCESS] = "success",
[SOCKET_FAILURE_RESOURCES] = "resources",
[SOCKET_FAILURE_TIMEOUT] = "timeout",
[SOCKET_FAILURE_EXIT_CODE] = "exit-code",
[SOCKET_FAILURE_SIGNAL] = "signal",
[SOCKET_FAILURE_CORE_DUMP] = "core-dump",
[SOCKET_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
[SOCKET_FAILURE_TRIGGER_LIMIT_HIT] = "trigger-limit-hit",
[SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit"
};
DEFINE_STRING_TABLE_LOOKUP(socket_result, SocketResult);

View File

@ -38,7 +38,6 @@ typedef enum SocketResult {
SOCKET_FAILURE_START_LIMIT_HIT,
SOCKET_FAILURE_TRIGGER_LIMIT_HIT,
SOCKET_FAILURE_SERVICE_START_LIMIT_HIT,
SOCKET_FAILURE_SERVICE_CONDITION_FAILED,
_SOCKET_RESULT_MAX,
_SOCKET_RESULT_INVALID = -EINVAL,
} SocketResult;

View File

@ -598,11 +598,6 @@ static void timer_enter_running(Timer *t) {
return;
}
if (unit_has_failed_condition_or_assert(trigger)) {
timer_enter_dead(t, TIMER_FAILURE_UNIT_CONDITION_FAILED);
return;
}
r = manager_add_job(UNIT(t)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, NULL);
if (r < 0)
goto fail;
@ -916,10 +911,9 @@ static const char* const timer_base_table[_TIMER_BASE_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase);
static const char* const timer_result_table[_TIMER_RESULT_MAX] = {
[TIMER_SUCCESS] = "success",
[TIMER_FAILURE_RESOURCES] = "resources",
[TIMER_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
[TIMER_FAILURE_UNIT_CONDITION_FAILED] = "unit-condition-failed",
[TIMER_SUCCESS] = "success",
[TIMER_FAILURE_RESOURCES] = "resources",
[TIMER_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
};
DEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult);

View File

@ -32,7 +32,6 @@ typedef enum TimerResult {
TIMER_SUCCESS,
TIMER_FAILURE_RESOURCES,
TIMER_FAILURE_START_LIMIT_HIT,
TIMER_FAILURE_UNIT_CONDITION_FAILED,
_TIMER_RESULT_MAX,
_TIMER_RESULT_INVALID = -EINVAL,
} TimerResult;

View File

@ -1851,10 +1851,16 @@ static bool unit_verify_deps(Unit *u) {
int unit_start(Unit *u) {
UnitActiveState state;
Unit *following;
int r;
assert(u);
/* Check start rate limiting early so that failure conditions don't cause us to enter a busy loop. */
if (UNIT_VTABLE(u)->test_start_limit) {
int r = UNIT_VTABLE(u)->test_start_limit(u);
if (r < 0)
return r;
}
/* If this is already started, then this will succeed. Note that this will even succeed if this unit
* is not startable by the user. This is relied on to detect when we need to wait for units and when
* waiting is finished. */
@ -1904,13 +1910,6 @@ int unit_start(Unit *u) {
return unit_start(following);
}
/* Check start rate limiting early so that failure conditions don't cause us to enter a busy loop. */
if (UNIT_VTABLE(u)->test_start_limit) {
r = UNIT_VTABLE(u)->test_start_limit(u);
if (r < 0)
return r;
}
/* If it is stopped, but we cannot start it, then fail */
if (!UNIT_VTABLE(u)->start)
return -EBADR;
@ -5865,16 +5864,6 @@ Condition *unit_find_failed_condition(Unit *u) {
return failed_trigger && !has_succeeded_trigger ? failed_trigger : NULL;
}
bool unit_has_failed_condition_or_assert(Unit *u) {
if (dual_timestamp_is_set(&u->condition_timestamp) && !u->condition_result)
return true;
if (dual_timestamp_is_set(&u->assert_timestamp) && !u->assert_result)
return true;
return false;
}
static const char* const collect_mode_table[_COLLECT_MODE_MAX] = {
[COLLECT_INACTIVE] = "inactive",
[COLLECT_INACTIVE_OR_FAILED] = "inactive-or-failed",

View File

@ -988,8 +988,6 @@ int unit_thaw_vtable_common(Unit *u);
Condition *unit_find_failed_condition(Unit *u);
bool unit_has_failed_condition_or_assert(Unit *u);
/* Macros which append UNIT= or USER_UNIT= to the message */
#define log_unit_full_errno_zerook(unit, level, error, ...) \

View File

@ -52,10 +52,8 @@ case "$command" in
users=$(systemctl list-units 'user@*' --legend=no | sed -n -r 's/.*user@([0-9]+).service.*/\1/p')
for user in $users; do
for unit in "$@"; do
SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \
systemctl --user -M "$user@" set-property "$unit" Markers=+needs-restart &
done
SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \
systemctl --user -M "$user@" set-property "$unit" Markers=+needs-restart &
done
wait
;;

View File

@ -1,6 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
[Unit]
ConditionPathExists=/tmp/nonexistent
ConditionPathExists=!/tmp/nonexistent
[Service]
ExecStart=true

View File

@ -13,5 +13,5 @@ ExecStart=-socat -T20 OPEN:test.file UNIX-CONNECT:/run/test.ctl
# systemd enough time even on slower machines, to reach the trigger limit.
ExecStart=sleep 10
ExecStart=sh -x -c 'test "$(systemctl show test10.socket -P ActiveState)" = failed'
ExecStart=sh -x -c 'test "$(systemctl show test10.socket -P Result)" = service-condition-failed'
ExecStart=sh -x -c 'test "$(systemctl show test10.socket -P Result)" = trigger-limit-hit'
ExecStart=sh -x -c 'echo OK >/testok'

View File

@ -8,10 +8,10 @@ Type=oneshot
ExecStart=rm -f /tmp/nonexistent
ExecStart=systemctl start test63.path
ExecStart=touch /tmp/test63
# Make sure systemd has sufficient time to hit the start limit for test63.service.
ExecStart=sleep 2
# Ensure both the service and the corresponding path unit go inactive due to the failed condition check.
ExecStart=sh -x -c 'test "$(systemctl show test63.service -P ActiveState)" = inactive'
ExecStart=sh -x -c 'test "$(systemctl show test63.service -P Result)" = success'
ExecStart=sh -x -c 'test "$(systemctl show test63.service -P ActiveState)" = failed'
ExecStart=sh -x -c 'test "$(systemctl show test63.service -P Result)" = start-limit-hit'
ExecStart=sh -x -c 'test "$(systemctl show test63.path -P ActiveState)" = failed'
ExecStart=sh -x -c 'test "$(systemctl show test63.path -P Result)" = unit-condition-failed'
ExecStart=sh -x -c 'test "$(systemctl show test63.path -P Result)" = unit-start-limit-hit'
ExecStart=sh -x -c 'echo OK >/testok'