@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")
<!--property RestartUSecMax is not documented!-->
- <!--property RestartUSecCurrent is not documented!-->
+ <!--property RestartUSecNext is not documented!-->
<!--property TimeoutStartFailureMode is not documented!-->
<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"/>
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);
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),
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;
}
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);
* 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;
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.");
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_;