mirror of
https://github.com/systemd/systemd.git
synced 2024-10-26 17:27:41 +03:00
Merge pull request #34591 from teknoraver/timer
timer: introduce DeferReactivation setting
This commit is contained in:
commit
39b2ee5369
@ -387,6 +387,7 @@ Most timer unit settings are available to transient units.
|
||||
✓ AccuracySec=
|
||||
✓ RandomizedDelaySec=
|
||||
✓ FixedRandomDelay=
|
||||
✓ DeferReactivation=
|
||||
Unit=
|
||||
```
|
||||
|
||||
|
@ -8804,6 +8804,8 @@ node /org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2etimer {
|
||||
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 { ... };
|
||||
@ -8832,6 +8834,8 @@ node /org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2etimer {
|
||||
|
||||
<!--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"/>
|
||||
@ -8874,6 +8878,8 @@ node /org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2etimer {
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="RemainAfterElapse"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="DeferReactivation"/>
|
||||
|
||||
<!--End of Autogenerated section-->
|
||||
|
||||
<refsect2>
|
||||
@ -12386,5 +12392,9 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \
|
||||
<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>
|
||||
|
@ -305,6 +305,25 @@
|
||||
<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>
|
||||
|
@ -118,6 +118,7 @@ const sd_bus_vtable bus_timer_vtable[] = {
|
||||
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
|
||||
};
|
||||
|
||||
@ -233,6 +234,9 @@ static int bus_timer_set_transient_property(
|
||||
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;
|
||||
|
@ -570,6 +570,7 @@ Timer.Persistent, config_parse_bool,
|
||||
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
|
||||
|
@ -245,7 +245,8 @@ static void timer_dump(Unit *u, FILE *f, const char *prefix) {
|
||||
"%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",
|
||||
@ -255,7 +256,8 @@ static void timer_dump(Unit *u, FILE *f, const char *prefix) {
|
||||
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) {
|
||||
@ -391,12 +393,19 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
|
||||
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;
|
||||
|
@ -61,6 +61,7 @@ struct Timer {
|
||||
bool on_clock_change;
|
||||
bool on_timezone_change;
|
||||
bool fixed_random_delay;
|
||||
bool defer_reactivation;
|
||||
|
||||
char *stamp_path;
|
||||
};
|
||||
|
@ -2594,7 +2594,8 @@ static int bus_append_timer_property(sd_bus_message *m, const char *field, const
|
||||
"Persistent",
|
||||
"OnTimezoneChange",
|
||||
"OnClockChange",
|
||||
"FixedRandomDelay"))
|
||||
"FixedRandomDelay",
|
||||
"DeferReactivation"))
|
||||
return bus_append_parse_boolean(m, field, eq);
|
||||
|
||||
if (STR_IN_SET(field, "AccuracySec",
|
||||
|
@ -0,0 +1,6 @@
|
||||
[Unit]
|
||||
Description=Testing systemd timers
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=sh -c 'date +%%s >>/tmp/realtime-test.log ; sleep 5'
|
@ -0,0 +1,10 @@
|
||||
[Unit]
|
||||
Description=Testing systemd timers
|
||||
|
||||
[Timer]
|
||||
OnCalendar=*:*:0/5
|
||||
AccuracySec=1us
|
||||
DeferReactivation=true
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
@ -7,3 +7,5 @@ integration_tests += [
|
||||
'vm' : true,
|
||||
},
|
||||
]
|
||||
|
||||
testdata_subdirs += [meson.current_source_dir() / 'TEST-74-AUX-UTILS.units']
|
||||
|
@ -7,6 +7,7 @@ AllowedCPUs=
|
||||
AllowedMemoryNodes=
|
||||
AllowIsolate=
|
||||
Also=
|
||||
DeferReactivation=
|
||||
AmbientCapabilities=
|
||||
AssertACPower=
|
||||
AssertArchitecture=
|
||||
|
@ -33,6 +33,7 @@ Persistent=true
|
||||
AccuracySec=24h
|
||||
RandomizedDelaySec=234234234
|
||||
FixedRandomDelay=true
|
||||
DeferReactivation=true
|
||||
|
||||
Persistent=no
|
||||
Unit=foo.service
|
||||
|
23
test/units/TEST-74-AUX-UTILS.defer_reactivation.sh
Executable file
23
test/units/TEST-74-AUX-UTILS.defer_reactivation.sh
Executable file
@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env bash
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
set -eux
|
||||
set -o pipefail
|
||||
|
||||
systemctl start realtime-test.timer
|
||||
|
||||
sleep 35
|
||||
mindelta=10
|
||||
|
||||
last=
|
||||
while read -r time; do
|
||||
if [ -n "$last" ]; then
|
||||
delta=$((time - last))
|
||||
if [ "$delta" -lt $mindelta ]; then
|
||||
echo "Timer fired too early: $delta < $mindelta" >/failed
|
||||
break
|
||||
fi
|
||||
fi
|
||||
last=$time
|
||||
done </tmp/realtime-test.log
|
||||
|
||||
test ! -s /failed
|
Loading…
Reference in New Issue
Block a user