83 lines
3.6 KiB
Diff
83 lines
3.6 KiB
Diff
From bce3b46aaf8c7ad7ff7eeaafbf4b321ffdad9c07 Mon Sep 17 00:00:00 2001
|
|
From: Gibeom Gwon <gb.gwon@stackframe.dev>
|
|
Date: Sun, 6 Mar 2022 09:45:38 +0900
|
|
Subject: [PATCH] calendarspec: fix possibly skips next elapse
|
|
|
|
If the time unit changes after adding the repetition value, the
|
|
timer may skip the next elapse. This patch reset sub time units
|
|
to minimum value when upper unit is changed.
|
|
|
|
Fixes #22665.
|
|
|
|
(cherry picked from commit 1e582ede3b04d12aae11fc5378a446a392054f1c)
|
|
(cherry picked from commit 8d4c0d2383e72f30753bf33f206387bc03879ff8)
|
|
|
|
Conflict:NA
|
|
Reference:https://github.com/systemd/systemd-stable/commit/bce3b46aaf8c7ad7ff7eeaafbf4b321ffdad9c07
|
|
---
|
|
src/shared/calendarspec.c | 27 ++++++++++++++++++++-------
|
|
src/test/test-calendarspec.c | 2 ++
|
|
2 files changed, 22 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/src/shared/calendarspec.c b/src/shared/calendarspec.c
|
|
index bf24d8d5bb..238766c96a 100644
|
|
--- a/src/shared/calendarspec.c
|
|
+++ b/src/shared/calendarspec.c
|
|
@@ -1180,6 +1180,7 @@ static int find_matching_component(
|
|
|
|
static int tm_within_bounds(struct tm *tm, bool utc) {
|
|
struct tm t;
|
|
+ int cmp;
|
|
assert(tm);
|
|
|
|
/*
|
|
@@ -1194,13 +1195,25 @@ static int tm_within_bounds(struct tm *tm, bool utc) {
|
|
if (mktime_or_timegm(&t, utc) < 0)
|
|
return negative_errno();
|
|
|
|
- /* Did any normalization take place? If so, it was out of bounds before */
|
|
- int cmp = CMP(t.tm_year, tm->tm_year) ?:
|
|
- CMP(t.tm_mon, tm->tm_mon) ?:
|
|
- CMP(t.tm_mday, tm->tm_mday) ?:
|
|
- CMP(t.tm_hour, tm->tm_hour) ?:
|
|
- CMP(t.tm_min, tm->tm_min) ?:
|
|
- CMP(t.tm_sec, tm->tm_sec);
|
|
+ /*
|
|
+ * Did any normalization take place? If so, it was out of bounds before.
|
|
+ * Normalization could skip next elapse, e.g. result of normalizing 3-33
|
|
+ * is 4-2. This skips 4-1. So reset the sub time unit if upper unit was
|
|
+ * out of bounds. Normalization has occurred implies find_matching_component() > 0,
|
|
+ * other sub time units are already reset in find_next().
|
|
+ */
|
|
+ if ((cmp = CMP(t.tm_year, tm->tm_year)) != 0)
|
|
+ t.tm_mon = 0;
|
|
+ else if ((cmp = CMP(t.tm_mon, tm->tm_mon)) != 0)
|
|
+ t.tm_mday = 1;
|
|
+ else if ((cmp = CMP(t.tm_mday, tm->tm_mday)) != 0)
|
|
+ t.tm_hour = 0;
|
|
+ else if ((cmp = CMP(t.tm_hour, tm->tm_hour)) != 0)
|
|
+ t.tm_min = 0;
|
|
+ else if ((cmp = CMP(t.tm_min, tm->tm_min)) != 0)
|
|
+ t.tm_sec = 0;
|
|
+ else
|
|
+ cmp = CMP(t.tm_sec, tm->tm_sec);
|
|
|
|
if (cmp < 0)
|
|
return -EDEADLK; /* Refuse to go backward */
|
|
diff --git a/src/test/test-calendarspec.c b/src/test/test-calendarspec.c
|
|
index 4f1d0f64d5..bc5e56a238 100644
|
|
--- a/src/test/test-calendarspec.c
|
|
+++ b/src/test/test-calendarspec.c
|
|
@@ -201,6 +201,8 @@ int main(int argc, char* argv[]) {
|
|
test_next("2016-02~01 UTC", "", 12345, 1456704000000000);
|
|
test_next("Mon 2017-05~01..07 UTC", "", 12345, 1496016000000000);
|
|
test_next("Mon 2017-05~07/1 UTC", "", 12345, 1496016000000000);
|
|
+ test_next("*-*-01/5 04:00:00 UTC", "", 1646010000000000, 1646107200000000);
|
|
+ test_next("*-01/7-01 04:00:00 UTC", "", 1664607600000000, 1672545600000000);
|
|
test_next("2017-08-06 9,11,13,15,17:00 UTC", "", 1502029800000000, 1502031600000000);
|
|
test_next("2017-08-06 9..17/2:00 UTC", "", 1502029800000000, 1502031600000000);
|
|
test_next("2016-12-* 3..21/6:00 UTC", "", 1482613200000001, 1482634800000000);
|
|
--
|
|
2.33.0
|
|
|