✓ AccuracySec=
✓ RandomizedDelaySec=
✓ FixedRandomDelay=
+✓ DeferReactivation=
Unit=
```
readonly b WakeSystem = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b RemainAfterElapse = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+ readonly b DeferReactivation = ...;
};
interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... };
<!--property RemainAfterElapse is not documented!-->
+ <!--property DeferReactivation is not documented!-->
+
<!--Autogenerated cross-references for systemd.directives, do not edit-->
<variablelist class="dbus-interface" generated="True" extra-ref="org.freedesktop.systemd1.Unit"/>
<variablelist class="dbus-property" generated="True" extra-ref="RemainAfterElapse"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="DeferReactivation"/>
+
<!--End of Autogenerated section-->
<refsect2>
<title>Job Objects</title>
<para><varname>ActivationDetails</varname> was added in version 252.</para>
</refsect2>
+ <refsect2>
+ <title>Timer Objects</title>
+ <para><varname>DeferReactivation</varname> was added in version 257.</para>
+ </refsect2>
</refsect1>
</refentry>
<xi:include href="version-info.xml" xpointer="v247"/></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>DeferReactivation=</varname></term>
+
+ <listitem><para>Takes a boolean argument. When enabled, the timer schedules the next elapse based on
+ the trigger unit entering inactivity, instead of the last trigger time.
+ This is most apparent in the case where the service unit takes longer to run than the timer interval.
+ With this setting enabled, the timer will schedule the next elapse based on when the service finishes
+ running, and so it will have to wait until the next realtime elapse time to trigger.
+ Otherwise, the default behavior is for the timer unit to immediately trigger again once the service
+ finishes running. This happens because the timer schedules the next elapse based on the previous trigger
+ time, and since the interval is shorter than the service runtime, that elapse will be in the past,
+ causing it to immediately trigger once done.</para>
+
+ <para>This setting has no effect if a realtime timer has not been specified with
+ <varname>OnCalendar=</varname>. Defaults to <option>false</option>.</para>
+
+ <xi:include href="version-info.xml" xpointer="v257"/></listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>OnClockChange=</varname></term>
<term><varname>OnTimezoneChange=</varname></term>
SD_BUS_PROPERTY("Persistent", "b", bus_property_get_bool, offsetof(Timer, persistent), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("WakeSystem", "b", bus_property_get_bool, offsetof(Timer, wake_system), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RemainAfterElapse", "b", bus_property_get_bool, offsetof(Timer, remain_after_elapse), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DeferReactivation", "b", bus_property_get_bool, offsetof(Timer, defer_reactivation), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_VTABLE_END
};
if (streq(name, "OnClockChange"))
return bus_set_transient_bool(u, name, &t->on_clock_change, message, flags, error);
+ if (streq(name, "DeferReactivation"))
+ return bus_set_transient_bool(u, name, &t->defer_reactivation, message, flags, error);
+
if (streq(name, "TimersMonotonic")) {
const char *base_name;
usec_t usec;
Timer.WakeSystem, config_parse_bool, 0, offsetof(Timer, wake_system)
Timer.RemainAfterElapse, config_parse_bool, 0, offsetof(Timer, remain_after_elapse)
Timer.FixedRandomDelay, config_parse_bool, 0, offsetof(Timer, fixed_random_delay)
+Timer.DeferReactivation, config_parse_bool, 0, offsetof(Timer, defer_reactivation)
Timer.AccuracySec, config_parse_sec, 0, offsetof(Timer, accuracy_usec)
Timer.RandomizedDelaySec, config_parse_sec, 0, offsetof(Timer, random_usec)
Timer.Unit, config_parse_trigger_unit, 0, 0
"%sRemainAfterElapse: %s\n"
"%sFixedRandomDelay: %s\n"
"%sOnClockChange: %s\n"
- "%sOnTimeZoneChange: %s\n",
+ "%sOnTimeZoneChange: %s\n"
+ "%sDeferReactivation: %s\n",
prefix, timer_state_to_string(t->state),
prefix, timer_result_to_string(t->result),
prefix, trigger ? trigger->id : "n/a",
prefix, yes_no(t->remain_after_elapse),
prefix, yes_no(t->fixed_random_delay),
prefix, yes_no(t->on_clock_change),
- prefix, yes_no(t->on_timezone_change));
+ prefix, yes_no(t->on_timezone_change),
+ prefix, yes_no(t->defer_reactivation));
LIST_FOREACH(value, v, t->values)
if (v->base == TIMER_CALENDAR) {
if (v->base == TIMER_CALENDAR) {
usec_t b, rebased;
- /* If we know the last time this was
- * triggered, schedule the job based relative
- * to that. If we don't, just start from
- * the activation time. */
+ /* If DeferReactivation= is enabled, schedule the job based on the last time
+ * the trigger unit entered inactivity. Otherwise, if we know the last time
+ * this was triggered, schedule the job based relative to that. If we don't,
+ * just start from the activation time or realtime. */
- if (dual_timestamp_is_set(&t->last_trigger))
+ if (t->defer_reactivation &&
+ dual_timestamp_is_set(&trigger->inactive_enter_timestamp)) {
+ if (dual_timestamp_is_set(&t->last_trigger))
+ b = MAX(trigger->inactive_enter_timestamp.realtime,
+ t->last_trigger.realtime);
+ else
+ b = trigger->inactive_enter_timestamp.realtime;
+ } else if (dual_timestamp_is_set(&t->last_trigger))
b = t->last_trigger.realtime;
else if (dual_timestamp_is_set(&UNIT(t)->inactive_exit_timestamp))
b = UNIT(t)->inactive_exit_timestamp.realtime;
bool on_clock_change;
bool on_timezone_change;
bool fixed_random_delay;
+ bool defer_reactivation;
char *stamp_path;
};
"Persistent",
"OnTimezoneChange",
"OnClockChange",
- "FixedRandomDelay"))
+ "FixedRandomDelay",
+ "DeferReactivation"))
return bus_append_parse_boolean(m, field, eq);
if (STR_IN_SET(field, "AccuracySec",
AllowedMemoryNodes=
AllowIsolate=
Also=
+DeferReactivation=
AmbientCapabilities=
AssertACPower=
AssertArchitecture=
AccuracySec=24h
RandomizedDelaySec=234234234
FixedRandomDelay=true
+DeferReactivation=true
Persistent=no
Unit=foo.service