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:
parent
ed2a4e8d78
commit
5171356eee
@ -2578,7 +2578,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
|
|||||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||||
readonly t RestartUSecMax = ...;
|
readonly t RestartUSecMax = ...;
|
||||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
|
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
|
||||||
readonly t RestartUSecCurrent = ...;
|
readonly t RestartUSecNext = ...;
|
||||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||||
readonly t TimeoutStartUSec = ...;
|
readonly t TimeoutStartUSec = ...;
|
||||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||||
@ -3208,7 +3208,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
|
|||||||
|
|
||||||
<!--property RestartUSecMax is not documented!-->
|
<!--property RestartUSecMax is not documented!-->
|
||||||
|
|
||||||
<!--property RestartUSecCurrent is not documented!-->
|
<!--property RestartUSecNext is not documented!-->
|
||||||
|
|
||||||
<!--property TimeoutStartFailureMode 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="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"/>
|
<variablelist class="dbus-property" generated="True" extra-ref="TimeoutStartUSec"/>
|
||||||
|
|
||||||
|
@ -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_restart, service_restart, ServiceRestart);
|
||||||
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action, emergency_action, EmergencyAction);
|
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_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_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(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);
|
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("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("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("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("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("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),
|
SD_BUS_PROPERTY("TimeoutAbortUSec", "t", property_get_timeout_abort_usec, 0, 0),
|
||||||
|
@ -268,38 +268,37 @@ static void service_start_watchdog(Service *s) {
|
|||||||
log_unit_warning_errno(UNIT(s), r, "Failed to install watchdog timer: %m");
|
log_unit_warning_errno(UNIT(s), r, "Failed to install watchdog timer: %m");
|
||||||
}
|
}
|
||||||
|
|
||||||
usec_t service_restart_usec(Service *s) {
|
usec_t service_restart_usec_next(Service *s) {
|
||||||
unsigned n_restarts;
|
unsigned n_restarts_next;
|
||||||
long double unit;
|
|
||||||
usec_t value;
|
usec_t value;
|
||||||
|
|
||||||
assert(s);
|
assert(s);
|
||||||
|
|
||||||
/* s->n_restarts is not yet updated when we're in these states, so let's add 1 to it manually.
|
/* When the service state is in SERVICE_*_BEFORE_AUTO_RESTART or SERVICE_AUTO_RESTART,
|
||||||
* Note that for SERVICE_AUTO_RESTART a restart job might have been enqueued,
|
* we still need to add 1 to s->n_restarts manually because s->n_restarts is not updated
|
||||||
* i.e. s->n_restarts is already increased. But we assume it's not since the time
|
* until a restart job is enqueued. Note that for SERVICE_AUTO_RESTART, that might have been
|
||||||
* between job enqueuing and running is usually neglectable compared to the time
|
* the case, i.e. s->n_restarts is already increased. But we assume it's not since the time
|
||||||
* we'll be sleeping. */
|
* between job enqueuing and running is usually neglectable compared to the time we'll be sleeping. */
|
||||||
n_restarts = s->n_restarts +
|
n_restarts_next = s->n_restarts + 1;
|
||||||
(IN_SET(s->state, SERVICE_DEAD_BEFORE_AUTO_RESTART, SERVICE_FAILED_BEFORE_AUTO_RESTART, SERVICE_AUTO_RESTART) ? 1 : 0);
|
|
||||||
|
|
||||||
/* n_restarts can equal to 0 if no restart has happened nor planned */
|
if (n_restarts_next <= 1 ||
|
||||||
if (n_restarts <= 1 ||
|
|
||||||
s->restart_steps == 0 ||
|
s->restart_steps == 0 ||
|
||||||
s->restart_usec_max == USEC_INFINITY ||
|
s->restart_usec_max == USEC_INFINITY ||
|
||||||
s->restart_usec >= s->restart_usec_max)
|
s->restart_usec >= s->restart_usec_max)
|
||||||
value = s->restart_usec;
|
value = s->restart_usec;
|
||||||
else if (n_restarts > s->restart_steps)
|
else if (n_restarts_next > s->restart_steps)
|
||||||
value = s->restart_usec_max;
|
value = s->restart_usec_max;
|
||||||
else {
|
else {
|
||||||
/* Enforced in service_verify() and above */
|
/* Enforced in service_verify() and above */
|
||||||
assert(s->restart_usec_max > s->restart_usec);
|
assert(s->restart_usec_max > s->restart_usec);
|
||||||
|
|
||||||
unit = powl(s->restart_usec_max - s->restart_usec, 1.0L / s->restart_steps);
|
/* ((restart_usec_max - restart_usec)^(1/restart_steps))^(n_restart_next - 1) */
|
||||||
value = usec_add(s->restart_usec, (usec_t) powl(unit, n_restarts - 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;
|
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));
|
return usec_add(UNIT(s)->state_change_timestamp.monotonic, service_timeout_abort_usec(s));
|
||||||
|
|
||||||
case SERVICE_AUTO_RESTART:
|
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:
|
case SERVICE_CLEANING:
|
||||||
return usec_add(UNIT(s)->state_change_timestamp.monotonic, s->exec_context.timeout_clean_usec);
|
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. */
|
* state from this transitionary UNIT_INACTIVE state by looking at the low-level states. */
|
||||||
service_set_state(s, restart_state);
|
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)
|
if (r < 0)
|
||||||
goto fail;
|
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)
|
if (s->restart_usec > 0)
|
||||||
log_unit_debug(UNIT(s),
|
log_unit_debug(UNIT(s),
|
||||||
"Service restart interval %s expired, scheduling restart.",
|
"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
|
else
|
||||||
log_unit_debug(UNIT(s),
|
log_unit_debug(UNIT(s),
|
||||||
"Service has no hold-off time (RestartSec=0), scheduling restart.");
|
"Service has no hold-off time (RestartSec=0), scheduling restart.");
|
||||||
|
@ -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);
|
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);
|
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_;
|
const char* service_restart_to_string(ServiceRestart i) _const_;
|
||||||
ServiceRestart service_restart_from_string(const char *s) _pure_;
|
ServiceRestart service_restart_from_string(const char *s) _pure_;
|
||||||
|
Loading…
Reference in New Issue
Block a user