From: Mike Yuan Date: Wed, 29 Mar 2023 20:04:22 +0000 (+0800) Subject: core: always calculate the next restart interval X-Git-Tag: v254-rc1~851 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5171356eeed4790bf2eeb864dfda0d04041dedf2;p=thirdparty%2Fsystemd.git core: always calculate the next restart interval Follow-up for #26902 and #26971 Let's always calculate the next restart interval since that's more useful. For that, we add 1 to s->n_restarts unconditionally, and change RestartUSecCurrent property to RestartUSecNext. --- diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml index 1a82a19bbdc..50680e6b37a 100644 --- a/man/org.freedesktop.systemd1.xml +++ b/man/org.freedesktop.systemd1.xml @@ -2578,7 +2578,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly t RestartUSecMax = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - readonly t RestartUSecCurrent = ...; + readonly t RestartUSecNext = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") readonly t TimeoutStartUSec = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("const") @@ -3208,7 +3208,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { - + @@ -3774,7 +3774,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { - + diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c index 742893370f6..a6758e616b1 100644 --- a/src/core/dbus-service.c +++ b/src/core/dbus-service.c @@ -35,7 +35,7 @@ static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, service_result, Service static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_restart, service_restart, ServiceRestart); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action, emergency_action, EmergencyAction); static BUS_DEFINE_PROPERTY_GET2(property_get_notify_access, "s", Service, service_get_notify_access, notify_access_to_string); -static BUS_DEFINE_PROPERTY_GET(property_get_restart_usec_current, "t", Service, service_restart_usec); +static BUS_DEFINE_PROPERTY_GET(property_get_restart_usec_next, "t", Service, service_restart_usec_next); static BUS_DEFINE_PROPERTY_GET(property_get_timeout_abort_usec, "t", Service, service_timeout_abort_usec); static BUS_DEFINE_PROPERTY_GET(property_get_watchdog_usec, "t", Service, service_get_watchdog_usec); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_timeout_failure_mode, service_timeout_failure_mode, ServiceTimeoutFailureMode); @@ -296,7 +296,7 @@ const sd_bus_vtable bus_service_vtable[] = { SD_BUS_PROPERTY("RestartUSec", "t", bus_property_get_usec, offsetof(Service, restart_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RestartSteps", "u", bus_property_get_unsigned, offsetof(Service, restart_steps), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RestartUSecMax", "t", bus_property_get_usec, offsetof(Service, restart_usec_max), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("RestartUSecCurrent", "t", property_get_restart_usec_current, 0, 0), + SD_BUS_PROPERTY("RestartUSecNext", "t", property_get_restart_usec_next, 0, 0), SD_BUS_PROPERTY("TimeoutStartUSec", "t", bus_property_get_usec, offsetof(Service, timeout_start_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Service, timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TimeoutAbortUSec", "t", property_get_timeout_abort_usec, 0, 0), diff --git a/src/core/service.c b/src/core/service.c index c4a7be890d6..e0e56af19c7 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -268,38 +268,37 @@ static void service_start_watchdog(Service *s) { log_unit_warning_errno(UNIT(s), r, "Failed to install watchdog timer: %m"); } -usec_t service_restart_usec(Service *s) { - unsigned n_restarts; - long double unit; +usec_t service_restart_usec_next(Service *s) { + unsigned n_restarts_next; usec_t value; assert(s); - /* s->n_restarts is not yet updated when we're in these states, so let's add 1 to it manually. - * Note that for SERVICE_AUTO_RESTART a restart job might have been enqueued, - * i.e. s->n_restarts is already increased. But we assume it's not since the time - * between job enqueuing and running is usually neglectable compared to the time - * we'll be sleeping. */ - n_restarts = s->n_restarts + - (IN_SET(s->state, SERVICE_DEAD_BEFORE_AUTO_RESTART, SERVICE_FAILED_BEFORE_AUTO_RESTART, SERVICE_AUTO_RESTART) ? 1 : 0); + /* When the service state is in SERVICE_*_BEFORE_AUTO_RESTART or SERVICE_AUTO_RESTART, + * we still need to add 1 to s->n_restarts manually because s->n_restarts is not updated + * until a restart job is enqueued. Note that for SERVICE_AUTO_RESTART, that might have been + * the case, i.e. s->n_restarts is already increased. But we assume it's not since the time + * between job enqueuing and running is usually neglectable compared to the time we'll be sleeping. */ + n_restarts_next = s->n_restarts + 1; - /* n_restarts can equal to 0 if no restart has happened nor planned */ - if (n_restarts <= 1 || + if (n_restarts_next <= 1 || s->restart_steps == 0 || s->restart_usec_max == USEC_INFINITY || s->restart_usec >= s->restart_usec_max) value = s->restart_usec; - else if (n_restarts > s->restart_steps) + else if (n_restarts_next > s->restart_steps) value = s->restart_usec_max; else { /* Enforced in service_verify() and above */ assert(s->restart_usec_max > s->restart_usec); - unit = powl(s->restart_usec_max - s->restart_usec, 1.0L / s->restart_steps); - value = usec_add(s->restart_usec, (usec_t) powl(unit, n_restarts - 1)); + /* ((restart_usec_max - restart_usec)^(1/restart_steps))^(n_restart_next - 1) */ + value = usec_add(s->restart_usec, + (usec_t) powl(s->restart_usec_max - s->restart_usec, + (long double) (n_restarts_next - 1) / s->restart_steps)); } - log_unit_debug(UNIT(s), "Restart interval calculated as: %s", FORMAT_TIMESPAN(value, 0)); + log_unit_debug(UNIT(s), "Next restart interval calculated as: %s", FORMAT_TIMESPAN(value, 0)); return value; } @@ -1270,7 +1269,7 @@ static usec_t service_coldplug_timeout(Service *s) { return usec_add(UNIT(s)->state_change_timestamp.monotonic, service_timeout_abort_usec(s)); case SERVICE_AUTO_RESTART: - return usec_add(UNIT(s)->inactive_enter_timestamp.monotonic, service_restart_usec(s)); + return usec_add(UNIT(s)->inactive_enter_timestamp.monotonic, service_restart_usec_next(s)); case SERVICE_CLEANING: return usec_add(UNIT(s)->state_change_timestamp.monotonic, s->exec_context.timeout_clean_usec); @@ -1963,7 +1962,7 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) * state from this transitionary UNIT_INACTIVE state by looking at the low-level states. */ service_set_state(s, restart_state); - r = service_arm_timer(s, /* relative= */ true, service_restart_usec(s)); + r = service_arm_timer(s, /* relative= */ true, service_restart_usec_next(s)); if (r < 0) goto fail; @@ -4200,7 +4199,7 @@ static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *us if (s->restart_usec > 0) log_unit_debug(UNIT(s), "Service restart interval %s expired, scheduling restart.", - FORMAT_TIMESPAN(service_restart_usec(s), USEC_PER_SEC)); + FORMAT_TIMESPAN(service_restart_usec_next(s), USEC_PER_SEC)); else log_unit_debug(UNIT(s), "Service has no hold-off time (RestartSec=0), scheduling restart."); diff --git a/src/core/service.h b/src/core/service.h index 156d32ca171..03edb18e31e 100644 --- a/src/core/service.h +++ b/src/core/service.h @@ -245,7 +245,7 @@ extern const UnitVTable service_vtable; int service_set_socket_fd(Service *s, int fd, struct Socket *socket, struct SocketPeer *peer, bool selinux_context_net); void service_close_socket_fd(Service *s); -usec_t service_restart_usec(Service *s); +usec_t service_restart_usec_next(Service *s); const char* service_restart_to_string(ServiceRestart i) _const_; ServiceRestart service_restart_from_string(const char *s) _pure_;