1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-22 17:35:35 +03:00

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.
This commit is contained in:
Mike Yuan 2023-03-30 04:04:22 +08:00 committed by Luca Boccassi
parent ed2a4e8d78
commit 5171356eee
4 changed files with 24 additions and 25 deletions

View File

@ -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 {
<!--property RestartUSecMax is not documented!-->
<!--property RestartUSecCurrent is not documented!-->
<!--property RestartUSecNext is not documented!-->
<!--property TimeoutStartFailureMode is not documented!-->
@ -3774,7 +3774,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<variablelist class="dbus-property" generated="True" extra-ref="RestartUSecMax"/>
<variablelist class="dbus-property" generated="True" extra-ref="RestartUSecCurrent"/>
<variablelist class="dbus-property" generated="True" extra-ref="RestartUSecNext"/>
<variablelist class="dbus-property" generated="True" extra-ref="TimeoutStartUSec"/>

View File

@ -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),

View File

@ -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.");

View File

@ -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_;