mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-22 13:33:56 +03:00
Merge pull request #21030 from DaanDeMeyer/path-skipped
core: Propagate condition failed state from service to path unit.
This commit is contained in:
commit
71bb9594e9
@ -72,3 +72,4 @@ Packages=
|
|||||||
strace
|
strace
|
||||||
tpm2-tss
|
tpm2-tss
|
||||||
less
|
less
|
||||||
|
netcat
|
||||||
|
@ -786,6 +786,11 @@ static void automount_enter_running(Automount *a) {
|
|||||||
goto fail;
|
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);
|
r = manager_add_job(UNIT(a)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, NULL);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_unit_warning(UNIT(a), "Failed to queue mount startup job: %s", bus_error_message(&error, r));
|
log_unit_warning(UNIT(a), "Failed to queue mount startup job: %s", bus_error_message(&error, r));
|
||||||
@ -1074,11 +1079,12 @@ static int automount_test_start_limit(Unit *u) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const char* const automount_result_table[_AUTOMOUNT_RESULT_MAX] = {
|
static const char* const automount_result_table[_AUTOMOUNT_RESULT_MAX] = {
|
||||||
[AUTOMOUNT_SUCCESS] = "success",
|
[AUTOMOUNT_SUCCESS] = "success",
|
||||||
[AUTOMOUNT_FAILURE_RESOURCES] = "resources",
|
[AUTOMOUNT_FAILURE_RESOURCES] = "resources",
|
||||||
[AUTOMOUNT_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
[AUTOMOUNT_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
||||||
[AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT] = "mount-start-limit-hit",
|
[AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT] = "mount-start-limit-hit",
|
||||||
[AUTOMOUNT_FAILURE_UNMOUNTED] = "unmounted",
|
[AUTOMOUNT_FAILURE_UNMOUNTED] = "unmounted",
|
||||||
|
[AUTOMOUNT_FAILURE_MOUNT_CONDITION_FAILED] = "mount-condition-failed",
|
||||||
};
|
};
|
||||||
|
|
||||||
DEFINE_STRING_TABLE_LOOKUP(automount_result, AutomountResult);
|
DEFINE_STRING_TABLE_LOOKUP(automount_result, AutomountResult);
|
||||||
|
@ -11,6 +11,7 @@ typedef enum AutomountResult {
|
|||||||
AUTOMOUNT_FAILURE_UNMOUNTED,
|
AUTOMOUNT_FAILURE_UNMOUNTED,
|
||||||
AUTOMOUNT_FAILURE_START_LIMIT_HIT,
|
AUTOMOUNT_FAILURE_START_LIMIT_HIT,
|
||||||
AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT,
|
AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT,
|
||||||
|
AUTOMOUNT_FAILURE_MOUNT_CONDITION_FAILED,
|
||||||
_AUTOMOUNT_RESULT_MAX,
|
_AUTOMOUNT_RESULT_MAX,
|
||||||
_AUTOMOUNT_RESULT_INVALID = -EINVAL,
|
_AUTOMOUNT_RESULT_INVALID = -EINVAL,
|
||||||
} AutomountResult;
|
} AutomountResult;
|
||||||
|
@ -480,7 +480,7 @@ static void path_enter_dead(Path *p, PathResult f) {
|
|||||||
p->result = f;
|
p->result = f;
|
||||||
|
|
||||||
unit_log_result(UNIT(p), p->result == PATH_SUCCESS, path_result_to_string(p->result));
|
unit_log_result(UNIT(p), p->result == PATH_SUCCESS, path_result_to_string(p->result));
|
||||||
path_set_state(p, p->result != PATH_SUCCESS ? PATH_FAILED : PATH_DEAD);
|
path_set_state(p, p->result == PATH_SUCCESS ? PATH_DEAD : PATH_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void path_enter_running(Path *p) {
|
static void path_enter_running(Path *p) {
|
||||||
@ -780,6 +780,11 @@ static void path_trigger_notify(Unit *u, Unit *other) {
|
|||||||
return;
|
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 */
|
/* Don't propagate anything if there's still a job queued */
|
||||||
if (other->job)
|
if (other->job)
|
||||||
return;
|
return;
|
||||||
@ -832,10 +837,11 @@ static const char* const path_type_table[_PATH_TYPE_MAX] = {
|
|||||||
DEFINE_STRING_TABLE_LOOKUP(path_type, PathType);
|
DEFINE_STRING_TABLE_LOOKUP(path_type, PathType);
|
||||||
|
|
||||||
static const char* const path_result_table[_PATH_RESULT_MAX] = {
|
static const char* const path_result_table[_PATH_RESULT_MAX] = {
|
||||||
[PATH_SUCCESS] = "success",
|
[PATH_SUCCESS] = "success",
|
||||||
[PATH_FAILURE_RESOURCES] = "resources",
|
[PATH_FAILURE_RESOURCES] = "resources",
|
||||||
[PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
[PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
||||||
[PATH_FAILURE_UNIT_START_LIMIT_HIT] = "unit-start-limit-hit",
|
[PATH_FAILURE_UNIT_START_LIMIT_HIT] = "unit-start-limit-hit",
|
||||||
|
[PATH_FAILURE_UNIT_CONDITION_FAILED] = "unit-condition-failed",
|
||||||
};
|
};
|
||||||
|
|
||||||
DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult);
|
DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult);
|
||||||
|
@ -46,6 +46,7 @@ typedef enum PathResult {
|
|||||||
PATH_FAILURE_RESOURCES,
|
PATH_FAILURE_RESOURCES,
|
||||||
PATH_FAILURE_START_LIMIT_HIT,
|
PATH_FAILURE_START_LIMIT_HIT,
|
||||||
PATH_FAILURE_UNIT_START_LIMIT_HIT,
|
PATH_FAILURE_UNIT_START_LIMIT_HIT,
|
||||||
|
PATH_FAILURE_UNIT_CONDITION_FAILED,
|
||||||
_PATH_RESULT_MAX,
|
_PATH_RESULT_MAX,
|
||||||
_PATH_RESULT_INVALID = -EINVAL,
|
_PATH_RESULT_INVALID = -EINVAL,
|
||||||
} PathResult;
|
} PathResult;
|
||||||
|
@ -2335,6 +2335,15 @@ static void socket_enter_running(Socket *s, int cfd_in) {
|
|||||||
goto refuse;
|
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) {
|
if (cfd < 0) {
|
||||||
bool pending = false;
|
bool pending = false;
|
||||||
Unit *other;
|
Unit *other;
|
||||||
@ -3444,15 +3453,16 @@ static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = {
|
|||||||
DEFINE_STRING_TABLE_LOOKUP(socket_exec_command, SocketExecCommand);
|
DEFINE_STRING_TABLE_LOOKUP(socket_exec_command, SocketExecCommand);
|
||||||
|
|
||||||
static const char* const socket_result_table[_SOCKET_RESULT_MAX] = {
|
static const char* const socket_result_table[_SOCKET_RESULT_MAX] = {
|
||||||
[SOCKET_SUCCESS] = "success",
|
[SOCKET_SUCCESS] = "success",
|
||||||
[SOCKET_FAILURE_RESOURCES] = "resources",
|
[SOCKET_FAILURE_RESOURCES] = "resources",
|
||||||
[SOCKET_FAILURE_TIMEOUT] = "timeout",
|
[SOCKET_FAILURE_TIMEOUT] = "timeout",
|
||||||
[SOCKET_FAILURE_EXIT_CODE] = "exit-code",
|
[SOCKET_FAILURE_EXIT_CODE] = "exit-code",
|
||||||
[SOCKET_FAILURE_SIGNAL] = "signal",
|
[SOCKET_FAILURE_SIGNAL] = "signal",
|
||||||
[SOCKET_FAILURE_CORE_DUMP] = "core-dump",
|
[SOCKET_FAILURE_CORE_DUMP] = "core-dump",
|
||||||
[SOCKET_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
[SOCKET_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
||||||
[SOCKET_FAILURE_TRIGGER_LIMIT_HIT] = "trigger-limit-hit",
|
[SOCKET_FAILURE_TRIGGER_LIMIT_HIT] = "trigger-limit-hit",
|
||||||
[SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit"
|
[SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit",
|
||||||
|
[SOCKET_FAILURE_SERVICE_CONDITION_FAILED] = "service-condition-failed",
|
||||||
};
|
};
|
||||||
|
|
||||||
DEFINE_STRING_TABLE_LOOKUP(socket_result, SocketResult);
|
DEFINE_STRING_TABLE_LOOKUP(socket_result, SocketResult);
|
||||||
|
@ -38,6 +38,7 @@ typedef enum SocketResult {
|
|||||||
SOCKET_FAILURE_START_LIMIT_HIT,
|
SOCKET_FAILURE_START_LIMIT_HIT,
|
||||||
SOCKET_FAILURE_TRIGGER_LIMIT_HIT,
|
SOCKET_FAILURE_TRIGGER_LIMIT_HIT,
|
||||||
SOCKET_FAILURE_SERVICE_START_LIMIT_HIT,
|
SOCKET_FAILURE_SERVICE_START_LIMIT_HIT,
|
||||||
|
SOCKET_FAILURE_SERVICE_CONDITION_FAILED,
|
||||||
_SOCKET_RESULT_MAX,
|
_SOCKET_RESULT_MAX,
|
||||||
_SOCKET_RESULT_INVALID = -EINVAL,
|
_SOCKET_RESULT_INVALID = -EINVAL,
|
||||||
} SocketResult;
|
} SocketResult;
|
||||||
|
@ -598,6 +598,11 @@ static void timer_enter_running(Timer *t) {
|
|||||||
return;
|
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);
|
r = manager_add_job(UNIT(t)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -911,9 +916,10 @@ static const char* const timer_base_table[_TIMER_BASE_MAX] = {
|
|||||||
DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase);
|
DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase);
|
||||||
|
|
||||||
static const char* const timer_result_table[_TIMER_RESULT_MAX] = {
|
static const char* const timer_result_table[_TIMER_RESULT_MAX] = {
|
||||||
[TIMER_SUCCESS] = "success",
|
[TIMER_SUCCESS] = "success",
|
||||||
[TIMER_FAILURE_RESOURCES] = "resources",
|
[TIMER_FAILURE_RESOURCES] = "resources",
|
||||||
[TIMER_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
[TIMER_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
||||||
|
[TIMER_FAILURE_UNIT_CONDITION_FAILED] = "unit-condition-failed",
|
||||||
};
|
};
|
||||||
|
|
||||||
DEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult);
|
DEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult);
|
||||||
|
@ -32,6 +32,7 @@ typedef enum TimerResult {
|
|||||||
TIMER_SUCCESS,
|
TIMER_SUCCESS,
|
||||||
TIMER_FAILURE_RESOURCES,
|
TIMER_FAILURE_RESOURCES,
|
||||||
TIMER_FAILURE_START_LIMIT_HIT,
|
TIMER_FAILURE_START_LIMIT_HIT,
|
||||||
|
TIMER_FAILURE_UNIT_CONDITION_FAILED,
|
||||||
_TIMER_RESULT_MAX,
|
_TIMER_RESULT_MAX,
|
||||||
_TIMER_RESULT_INVALID = -EINVAL,
|
_TIMER_RESULT_INVALID = -EINVAL,
|
||||||
} TimerResult;
|
} TimerResult;
|
||||||
|
@ -1851,16 +1851,10 @@ static bool unit_verify_deps(Unit *u) {
|
|||||||
int unit_start(Unit *u) {
|
int unit_start(Unit *u) {
|
||||||
UnitActiveState state;
|
UnitActiveState state;
|
||||||
Unit *following;
|
Unit *following;
|
||||||
|
int r;
|
||||||
|
|
||||||
assert(u);
|
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
|
/* 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
|
* is not startable by the user. This is relied on to detect when we need to wait for units and when
|
||||||
* waiting is finished. */
|
* waiting is finished. */
|
||||||
@ -1910,6 +1904,13 @@ int unit_start(Unit *u) {
|
|||||||
return unit_start(following);
|
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 it is stopped, but we cannot start it, then fail */
|
||||||
if (!UNIT_VTABLE(u)->start)
|
if (!UNIT_VTABLE(u)->start)
|
||||||
return -EBADR;
|
return -EBADR;
|
||||||
@ -5864,6 +5865,16 @@ Condition *unit_find_failed_condition(Unit *u) {
|
|||||||
return failed_trigger && !has_succeeded_trigger ? failed_trigger : NULL;
|
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] = {
|
static const char* const collect_mode_table[_COLLECT_MODE_MAX] = {
|
||||||
[COLLECT_INACTIVE] = "inactive",
|
[COLLECT_INACTIVE] = "inactive",
|
||||||
[COLLECT_INACTIVE_OR_FAILED] = "inactive-or-failed",
|
[COLLECT_INACTIVE_OR_FAILED] = "inactive-or-failed",
|
||||||
|
@ -988,6 +988,8 @@ int unit_thaw_vtable_common(Unit *u);
|
|||||||
|
|
||||||
Condition *unit_find_failed_condition(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 */
|
/* Macros which append UNIT= or USER_UNIT= to the message */
|
||||||
|
|
||||||
#define log_unit_full_errno_zerook(unit, level, error, ...) \
|
#define log_unit_full_errno_zerook(unit, level, error, ...) \
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
[Unit]
|
[Unit]
|
||||||
ConditionPathExists=!/tmp/nonexistent
|
ConditionPathExists=/tmp/nonexistent
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
ExecStart=true
|
ExecStart=true
|
||||||
|
@ -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.
|
# systemd enough time even on slower machines, to reach the trigger limit.
|
||||||
ExecStart=sleep 10
|
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 ActiveState)" = failed'
|
||||||
ExecStart=sh -x -c 'test "$(systemctl show test10.socket -P Result)" = trigger-limit-hit'
|
ExecStart=sh -x -c 'test "$(systemctl show test10.socket -P Result)" = service-condition-failed'
|
||||||
ExecStart=sh -x -c 'echo OK >/testok'
|
ExecStart=sh -x -c 'echo OK >/testok'
|
||||||
|
@ -8,10 +8,10 @@ Type=oneshot
|
|||||||
ExecStart=rm -f /tmp/nonexistent
|
ExecStart=rm -f /tmp/nonexistent
|
||||||
ExecStart=systemctl start test63.path
|
ExecStart=systemctl start test63.path
|
||||||
ExecStart=touch /tmp/test63
|
ExecStart=touch /tmp/test63
|
||||||
# Make sure systemd has sufficient time to hit the start limit for test63.service.
|
|
||||||
ExecStart=sleep 2
|
ExecStart=sleep 2
|
||||||
ExecStart=sh -x -c 'test "$(systemctl show test63.service -P ActiveState)" = failed'
|
# 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 Result)" = start-limit-hit'
|
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.path -P ActiveState)" = failed'
|
ExecStart=sh -x -c 'test "$(systemctl show test63.path -P ActiveState)" = failed'
|
||||||
ExecStart=sh -x -c 'test "$(systemctl show test63.path -P Result)" = unit-start-limit-hit'
|
ExecStart=sh -x -c 'test "$(systemctl show test63.path -P Result)" = unit-condition-failed'
|
||||||
ExecStart=sh -x -c 'echo OK >/testok'
|
ExecStart=sh -x -c 'echo OK >/testok'
|
||||||
|
Loading…
Reference in New Issue
Block a user