core: Add SERVICE_RUNNING_REVALIDATING state

For a Type=dbus service we sometimes want to keep treating it as running
while its bus name has briefly gone away (for example, due to a broker
restart).

SERVICE_RUNNING_REVALIDATING is active and keeps its main process like
SERVICE_RUNNING, but it's deliberately not part of the runtime timer
set, so RuntimeMaxSec= is paused while we sit in it.
This commit is contained in:
Chris Down
2026-09-01 02:12:52 +09:00
committed by Yu Watanabe
parent 9064524e44
commit 00cf56abbd
4 changed files with 13 additions and 3 deletions
+1
View File
@@ -233,6 +233,7 @@ static const char* const service_state_table[_SERVICE_STATE_MAX] = {
[SERVICE_START] = "start",
[SERVICE_START_POST] = "start-post",
[SERVICE_RUNNING] = "running",
[SERVICE_RUNNING_REVALIDATING] = "running-revalidating",
[SERVICE_EXITED] = "exited",
[SERVICE_REFRESH_EXTENSIONS] = "refresh-extensions",
[SERVICE_REFRESH_CREDENTIALS] = "refresh-credentials",
+1
View File
@@ -132,6 +132,7 @@ typedef enum ServiceState {
SERVICE_START,
SERVICE_START_POST,
SERVICE_RUNNING,
SERVICE_RUNNING_REVALIDATING, /* Temporarily waiting for the D-Bus name to reappear */
SERVICE_EXITED, /* Nothing is running anymore, but RemainAfterExit is true hence this is OK */
SERVICE_REFRESH_EXTENSIONS, /* Refreshing extensions for a reload request */
SERVICE_REFRESH_CREDENTIALS, /* ditto, but for credentials */
+1
View File
@@ -2048,6 +2048,7 @@ static bool manager_dbus_is_running(Manager *m, bool deserialized) {
return false;
if (!IN_SET(deserialized ? SERVICE(u)->deserialized_state : SERVICE(u)->state,
SERVICE_RUNNING,
SERVICE_RUNNING_REVALIDATING,
SERVICE_REFRESH_EXTENSIONS,
SERVICE_REFRESH_CREDENTIALS,
SERVICE_RELOAD,
+10 -3
View File
@@ -77,6 +77,7 @@ static const UnitActiveState state_translation_table[_SERVICE_STATE_MAX] = {
[SERVICE_START] = UNIT_ACTIVATING,
[SERVICE_START_POST] = UNIT_ACTIVATING,
[SERVICE_RUNNING] = UNIT_ACTIVE,
[SERVICE_RUNNING_REVALIDATING] = UNIT_ACTIVE,
[SERVICE_EXITED] = UNIT_ACTIVE,
[SERVICE_REFRESH_EXTENSIONS] = UNIT_REFRESHING,
[SERVICE_REFRESH_CREDENTIALS] = UNIT_REFRESHING,
@@ -111,6 +112,7 @@ static const UnitActiveState state_translation_table_idle[_SERVICE_STATE_MAX] =
[SERVICE_START] = UNIT_ACTIVE,
[SERVICE_START_POST] = UNIT_ACTIVE,
[SERVICE_RUNNING] = UNIT_ACTIVE,
[SERVICE_RUNNING_REVALIDATING] = UNIT_ACTIVE,
[SERVICE_EXITED] = UNIT_ACTIVE,
[SERVICE_REFRESH_EXTENSIONS] = UNIT_REFRESHING,
[SERVICE_REFRESH_CREDENTIALS] = UNIT_REFRESHING,
@@ -153,7 +155,7 @@ static void service_set_state(Service *s, ServiceState state);
static bool SERVICE_STATE_WITH_MAIN_PROCESS(ServiceState state) {
return IN_SET(state,
SERVICE_START, SERVICE_START_POST,
SERVICE_RUNNING,
SERVICE_RUNNING, SERVICE_RUNNING_REVALIDATING,
SERVICE_REFRESH_EXTENSIONS, SERVICE_REFRESH_CREDENTIALS,
SERVICE_RELOAD, SERVICE_RELOAD_SIGNAL, SERVICE_RELOAD_NOTIFY, SERVICE_RELOAD_POST,
SERVICE_MOUNTING,
@@ -175,7 +177,7 @@ static bool SERVICE_STATE_WITH_CONTROL_PROCESS(ServiceState state) {
static bool SERVICE_STATE_WITH_WATCHDOG(ServiceState state) {
return IN_SET(state,
SERVICE_START_POST,
SERVICE_RUNNING,
SERVICE_RUNNING, SERVICE_RUNNING_REVALIDATING,
SERVICE_REFRESH_EXTENSIONS, SERVICE_REFRESH_CREDENTIALS,
SERVICE_RELOAD, SERVICE_RELOAD_SIGNAL, SERVICE_RELOAD_NOTIFY, SERVICE_RELOAD_POST,
SERVICE_MOUNTING);
@@ -3677,6 +3679,7 @@ static int service_stop(Unit *u) {
return 0;
case SERVICE_RUNNING:
case SERVICE_RUNNING_REVALIDATING:
case SERVICE_EXITED:
service_enter_stop(s, SERVICE_SUCCESS);
return 1;
@@ -3695,7 +3698,7 @@ static int service_stop(Unit *u) {
static int service_reload(Unit *u) {
Service *s = ASSERT_PTR(SERVICE(u));
assert(IN_SET(s->state, SERVICE_RUNNING, SERVICE_EXITED));
assert(IN_SET(s->state, SERVICE_RUNNING, SERVICE_RUNNING_REVALIDATING, SERVICE_EXITED));
s->reload_result = SERVICE_SUCCESS;
s->refreshed_mask = 0;
@@ -4593,6 +4596,7 @@ static void service_notify_cgroup_empty_event(Unit *u) {
break;
case SERVICE_RUNNING:
case SERVICE_RUNNING_REVALIDATING:
/* service_enter_running() will figure out what to do */
service_enter_running(s, SERVICE_SUCCESS);
break;
@@ -4654,6 +4658,7 @@ static void service_notify_cgroup_oom_event(Unit *u, bool managed_oom) {
case SERVICE_EXITED:
case SERVICE_RUNNING:
case SERVICE_RUNNING_REVALIDATING:
if (s->oom_policy == OOM_STOP)
service_enter_stop(s, SERVICE_FAILURE_OOM_KILL);
else if (s->oom_policy == OOM_KILL)
@@ -4818,6 +4823,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
_fallthrough_;
case SERVICE_RUNNING:
case SERVICE_RUNNING_REVALIDATING:
service_enter_running(s, f);
break;
@@ -6009,6 +6015,7 @@ static bool service_needs_console(Unit *u) {
SERVICE_START,
SERVICE_START_POST,
SERVICE_RUNNING,
SERVICE_RUNNING_REVALIDATING,
SERVICE_REFRESH_EXTENSIONS,
SERVICE_REFRESH_CREDENTIALS,
SERVICE_RELOAD,