Package: cron
Version: 3.0pl1-100
Severity: normal
Jobs scheduled to run between 1 and 2 am
are not run when time moves forward
for 1-3 hours (at the beginning of DST) and
are run twice when time moves backward
for 1-3 hours (at the end of DST).
Included is the patch against current trunk.
*** pkg-cron-trunk-dst.diff
Index: cron.c
===================================================================
--- cron.c (revision 413)
+++ cron.c (working copy)
@@ -37,7 +37,7 @@
static void usage __P((void)),
run_reboot_jobs __P((cron_db *)),
find_jobs __P((time_min, cron_db *, int, int)),
- set_time __P((void)),
+ set_time __P((int)),
cron_sleep __P((time_min)),
#ifdef USE_SIGCHLD
sigchld_handler __P((int)),
@@ -152,7 +152,7 @@
#endif
load_database(&database);
- set_time();
+ set_time(TRUE);
run_reboot_jobs(&database);
timeRunning = virtualTime = clockTime;
@@ -173,7 +173,7 @@
/* ... wait for the time (in minutes) to change ... */
do {
cron_sleep(timeRunning + 1);
- set_time();
+ set_time(FALSE);
} while (clockTime == timeRunning);
timeRunning = clockTime;
@@ -186,6 +186,9 @@
*/
timeDiff = timeRunning - virtualTime;
+ Debug(DSCH, ("[%d] pulse: %d = %d - %d\n",
+ getpid(), timeDiff, timeRunning, virtualTime));
+
/* shortcut for the most common case */
if (timeDiff == 1) {
virtualTime = timeRunning;
@@ -239,7 +242,7 @@
sleep(10);
virtualTime++;
find_jobs(virtualTime, &database,
FALSE, TRUE);
- set_time();
+ set_time(FALSE);
} while (virtualTime< timeRunning &&
clockTime == timeRunning);
break;
@@ -326,7 +329,7 @@
int doNonWild;
{
time_t virtualSecond = vtime * SECONDS_PER_MINUTE;
- register struct tm *tm = localtime(&virtualSecond);
+ register struct tm *tm = gmtime(&virtualSecond);
register int minute, hour, dom, month, dow;
register user *u;
register entry *e;
@@ -375,10 +378,22 @@
* note that clockTime is a unix wallclock time converted to minutes
*/
static void
-set_time()
+set_time(int initialize)
{
- StartTime = time((time_t *)0);
- clockTime = StartTime / (unsigned long)SECONDS_PER_MINUTE;
+ struct tm tm;
+ static int isdst;
+
+ StartTime = time(NULL);
+
+ /* We adjust the time to GMT so we can catch DST changes. */
+ tm = *localtime(&StartTime);
+ if (initialize || tm.tm_isdst != isdst) {
+ isdst = tm.tm_isdst;
+ GMToff = get_gmtoff(&StartTime, &tm);
+ Debug(DSCH, ("[%ld] GMToff=%ld\n",
+ (long)getpid(), (long)GMToff))
+ }
+ clockTime = (StartTime + GMToff) / (time_t)SECONDS_PER_MINUTE;
}
/*
@@ -390,12 +405,19 @@
{
register int seconds_to_wait;
- seconds_to_wait = (int)(target*SECONDS_PER_MINUTE - time((time_t*)0)) +
1;
+ time_t t1, t2;
+ t1 = time(NULL) + GMToff;
+
+ seconds_to_wait = (int)(target * SECONDS_PER_MINUTE - t1) + 1;
Debug(DSCH, ("[%d] TargetTime=%ld, sec-to-wait=%d\n",
getpid(), (long)target*SECONDS_PER_MINUTE, seconds_to_wait))
- if (seconds_to_wait > 0 && seconds_to_wait< 65)
+ while (seconds_to_wait > 0 && seconds_to_wait< 65) {
sleep((unsigned int) seconds_to_wait);
+ t2 = time(NULL) + GMToff;
+ seconds_to_wait -= (int)(t2 - t1);
+ t1 = t2;
+ }
}
Index: cron.h
===================================================================
--- cron.h (revision 413)
+++ cron.h (working copy)
@@ -279,6 +279,7 @@
time_min timeRunning;
time_min virtualTime;
time_min clockTime;
+static long GMToff;
int stay_foreground;
int lsbsysinit_mode;
Index: misc.c
===================================================================
--- misc.c (revision 413)
+++ misc.c (working copy)
@@ -718,3 +718,38 @@
}
int swap_uids_back() { return swap_uids(); }
#endif /*HAVE_SAVED_UIDS*/
+
+
+/* Return the offset from GMT in seconds (algorithm taken from sendmail).
+ *
+ * warning:
+ * clobbers the static storage space used by localtime() and gmtime().
+ * If the local pointer is non-NULL it *must* point to a local copy.
+ */
+#ifndef HAVE_TM_GMTOFF
+long get_gmtoff(time_t *clock, struct tm *local)
+{
+ struct tm gmt;
+ long offset;
+
+ gmt = *gmtime(clock);
+ if (local == NULL)
+ local = localtime(clock);
+
+ offset = (local->tm_sec - gmt.tm_sec) +
+ ((local->tm_min - gmt.tm_min) * 60) +
+ ((local->tm_hour - gmt.tm_hour) * 3600);
+
+ /* Timezone may cause year rollover to happen on a different day. */
+ if (local->tm_year < gmt.tm_year)
+ offset -= 24 * 3600;
+ else if (local->tm_year > gmt.tm_year)
+ offset -= 24 * 3600;
+ else if (local->tm_yday < gmt.tm_yday)
+ offset -= 24 * 3600;
+ else if (local->tm_yday > gmt.tm_yday)
+ offset += 24 * 3600;
+
+ return (offset);
+}
+#endif /* HAVE_TM_GMTOFF */
-- System Information:
Debian Release: 4.0
APT prefers stable
APT policy: (500, 'stable')
Architecture: amd64 (x86_64)
Shell: /bin/sh linked to /bin/bash
Kernel: Linux 2.6.22-4-amd64
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Versions of packages cron depends on:
ii adduser 3.102 Add and remove users and groups
ii debianutils 2.17 Miscellaneous utilities specific t
ii libc6 2.3.6.ds1-13etch5 GNU C Library: Shared libraries
ii libpam0g 0.79-5 Pluggable Authentication Modules l
ii libselinux1 1.32-3 SELinux shared libraries
ii lsb-base 3.1-23.2etch1 Linux Standard Base 3.1 init scrip
Versions of packages cron recommends:
ii postfix [mail-transport-agent 2.3.8-2 A high-performance mail transport
-- no debconf information
--
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]