This is for historical interest only, as the patch was merged as of 3.0pl1-152.
See Bug Report #1019716 for more information.
- Create cron in
/etc/cron.d/$namerunning at a specific hour. - Change system time with
dpkg-reconfigure tzdata. - Without issuing a
systemctl restart cron, the change will not be seen by crond, and the job will run at the old timezone.
Compiled with DDEBUGGING=1 and -g, using cron_3.0pl1-137 in Debian 11.
File to follow along with is here.
GMToff only responds to cron restarts - this is expected since the loop passes FALSE into set_time().
As such, clockTime (which is startTime + GMToff), will not change. timeRunning is set equal to clockTime, and
timeDiff is calculated as timeRunning - virtualTime.
The result is that jobs will execute according to the timezone present when cron.service was started.
Once system time is shifted forward, gdb is immediately launched (you may need to time this to launch at the start of a minute).
At this time, wakeupKind has not been assigned yet, and has a random value since it isn't initialized.
(gdb) f 4
#4 0x0000562f6e861b3f in main (argc=2, argv=0x7ffcfd281c88) at cron.c:169
169 cron_sleep(timeRunning + 1);
(gdb) p GMToff
$1 = -18000
(gdb) info locals
timeDiff = 1
wakeupKind = 21917
database = {head = 0x559da27b7a50, tail = 0x559da27c9310, user_mtime = 1662925987, sys_mtime = 1614033804, sysd_mtime = 1662945190}
cs = 0x7f7376399c0c "UTF-8"After some time, if gdb is launched again or otherwise reloaded, the following data can be observed.
Notably, GMToff has not changed despite system time having been shifted forward by an hour.
(gdb) f 4
#4 0x0000562f6e861b3f in main (argc=2, argv=0x7ffcfd281c88) at cron.c:169
169 cron_sleep(timeRunning + 1);
(gdb) p GMToff
$1 = -18000
(gdb) info locals
timeDiff = 2
wakeupKind = 1
database = {head = 0x559da27b7a50, tail = 0x559da27c9310, user_mtime = 1662925987, sys_mtime = 1614033804, sysd_mtime = 1662945190}
cs = 0x7f7376399c0c "UTF-8"If cron is restarted, the change to GMToff is immediate, and after some time, timeDiff will be recalculated and will
set wakeupKind accordingly, and the job will fire at its next scheduled time.
(gdb) f 4
#4 0x0000562f6e861b3f in main (argc=2, argv=0x7ffcfd281c88) at cron.c:169
169 cron_sleep(timeRunning + 1);
(gdb) p GMToff
$1 = -14400
(gdb) info locals
timeDiff = 2
wakeupKind = 1
database = {head = 0x562f6ff83c50, tail = 0x562f6ff97300, user_mtime = 1662925987, sys_mtime = 1614033804, sysd_mtime = 1662945190}
cs = 0x7f6ff8198c0c "UTF-8"If instead, the calculation for GMToff is moved out of the loop in set_time() such that it's calculated at every call, then after one minute
the offset will be noted.
(gdb) f 4
#4 0x000056220f044b3f in main (argc=2, argv=0x7ffc42e27598) at cron.c:169
169 cron_sleep(timeRunning + 1);
(gdb) p GMToff
$1 = -14400
(gdb) info locals
timeDiff = 62
wakeupKind = 2
database = {head = 0x562210237a50, tail = 0x562210249310, user_mtime = 1662925987, sys_mtime = 1614033804, sysd_mtime = 1662942515}
cs = 0x7f2ff76e3c0c "UTF-8"Then, the internal time tracking will be updated, and the job will fire at its next scheduled time.
(gdb) f 4
#4 0x000055662b61cb3f in main (argc=2, argv=0x7ffcb38aa688) at cron.c:169
169 cron_sleep(timeRunning + 1);
(gdb) p GMToff
$1 = -14400
(gdb) info locals
timeDiff = 1
wakeupKind = 2
database = {head = 0x55662b961a50, tail = 0x55662b973310, user_mtime = 1662925987, sys_mtime = 1614033804, sysd_mtime = 1662945190}
cs = 0x7ff3ea3a4c0c "UTF-8"diff --git a/cron.c b/cron.c
index 613e7bf..7b0b69c 100644
--- a/cron.c
+++ b/cron.c
@@ -372,9 +372,9 @@ set_time(int initialize)
/* We adjust the time to GMT so we can catch DST changes. */
tm = *localtime(&StartTime);
+ GMToff = get_gmtoff(&StartTime, &tm);
if (initialize || tm.tm_isdst != isdst) {
isdst = tm.tm_isdst;
- GMToff = get_gmtoff(&StartTime, &tm);
Debug(DSCH, ("[%d] GMToff=%ld\n",
getpid(), (long)GMToff))
}