Gitweb:
https://git.exim.org/exim.git/commitdiff/c9bce82e3064126be34d85280d0a7fbf65b3abec
Commit: c9bce82e3064126be34d85280d0a7fbf65b3abec
Parent: 62b2ccce05a9a3127736d84d20e2bbe7b0885287
Author: Jeremy Harris <jgh146exb@???>
AuthorDate: Tue Jun 30 21:16:42 2020 +0100
Committer: Jeremy Harris <jgh146exb@???>
CommitDate: Tue Jun 30 21:16:42 2020 +0100
Fix message-reception clock usage. Bug 2615
Broken-by: 6906c131d1 (4.94)
---
doc/doc-txt/ChangeLog | 8 +++++++
src/src/exim.c | 60 ++++++++++++++++++++++++++++++---------------------
src/src/functions.h | 1 +
src/src/receive.c | 2 +-
4 files changed, 45 insertions(+), 26 deletions(-)
diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index 41a9629..83908a5 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -73,6 +73,14 @@ JH/15 Fix "spam" ACL condition. Previously, tainted values for the "name"
argument resulted in a trap. There is no reason to disallow such; this
was a coding error.
+JH/16 Bug 2615: Fix pause during message reception, on systems that have been
+ suspended/resumed. This Linux CLOCK_MONOTONIC does not account for time
+ spent suspended, ignoring the Posix definintion. Previously we assumed
+ it did and a constant offset from real time could be used as a correction.
+ Change to using the same clock source for the start-of-message and the
+ post-message next-tick-wait. Also change to using CLOCK_BOOTTIME if it
+ exists, just to get a clock slightly more aligned to reality.
+
Exim version 4.94
-----------------
diff --git a/src/src/exim.c b/src/src/exim.c
index 9d3d456..dd3a17f 100644
--- a/src/src/exim.c
+++ b/src/src/exim.c
@@ -383,14 +383,20 @@ return 0;
*************************************************/
#ifdef _POSIX_MONOTONIC_CLOCK
-/* Amount CLOCK_MONOTONIC is behind realtime, at startup. */
+# ifdef CLOCK_BOOTTIME
+# define EXIM_CLOCKTYPE CLOCK_BOOTTIME
+# else
+# define EXIM_CLOCKTYPE CLOCK_MONOTONIC
+# endif
+
+/* Amount EXIM_CLOCK is behind realtime, at startup. */
static struct timespec offset_ts;
static void
exim_clock_init(void)
{
struct timeval tv;
-if (clock_gettime(CLOCK_MONOTONIC, &offset_ts) != 0) return;
+if (clock_gettime(EXIM_CLOCKTYPE, &offset_ts) != 0) return;
(void)gettimeofday(&tv, NULL);
offset_ts.tv_sec = tv.tv_sec - offset_ts.tv_sec;
offset_ts.tv_nsec = tv.tv_usec * 1000 - offset_ts.tv_nsec;
@@ -401,6 +407,29 @@ offset_ts.tv_nsec += 1000*1000*1000;
#endif
+void
+exim_gettime(struct timeval * tv)
+{
+#ifdef _POSIX_MONOTONIC_CLOCK
+struct timespec now_ts;
+
+if (clock_gettime(EXIM_CLOCKTYPE, &now_ts) == 0)
+ {
+ now_ts.tv_sec += offset_ts.tv_sec;
+ if ((now_ts.tv_nsec += offset_ts.tv_nsec) >= 1000*1000*1000)
+ {
+ now_ts.tv_sec++;
+ now_ts.tv_nsec -= 1000*1000*1000;
+ }
+ tv->tv_sec = now_ts.tv_sec;
+ tv->tv_usec = now_ts.tv_nsec / 1000;
+ }
+else
+#endif
+ (void)gettimeofday(tv, NULL);
+}
+
+
/* Exim uses a time + a pid to generate a unique identifier in two places: its
message IDs, and in file names for maildir deliveries. Because some OS now
re-use pids within the same second, sub-second times are now being used.
@@ -427,28 +456,9 @@ exim_wait_tick(struct timeval * tgt_tv, int resolution)
struct timeval now_tv;
long int now_true_usec;
-#ifdef _POSIX_MONOTONIC_CLOCK
-struct timespec now_ts;
-
-if (clock_gettime(CLOCK_MONOTONIC, &now_ts) == 0)
- {
- now_ts.tv_sec += offset_ts.tv_sec;
- if ((now_ts.tv_nsec += offset_ts.tv_nsec) >= 1000*1000*1000)
- {
- now_ts.tv_sec++;
- now_ts.tv_nsec -= 1000*1000*1000;
- }
- now_tv.tv_sec = now_ts.tv_sec;
- now_true_usec = (now_ts.tv_nsec / (resolution * 1000)) * resolution;
- now_tv.tv_usec = now_true_usec;
- }
-else
-#endif
- {
- (void)gettimeofday(&now_tv, NULL);
- now_true_usec = now_tv.tv_usec;
- now_tv.tv_usec = (now_true_usec/resolution) * resolution;
- }
+exim_gettime(&now_tv);
+now_true_usec = now_tv.tv_usec;
+now_tv.tv_usec = (now_true_usec/resolution) * resolution;
while (exim_tvcmp(&now_tv, tgt_tv) <= 0)
{
@@ -1728,7 +1738,7 @@ make quite sure. */
setlocale(LC_ALL, "C");
-/* Get the offset between CLOCK_MONOTONIC and wallclock */
+/* Get the offset between CLOCK_MONOTONIC/CLOCK_BOOTTIME and wallclock */
#ifdef _POSIX_MONOTONIC_CLOCK
exim_clock_init();
diff --git a/src/src/functions.h b/src/src/functions.h
index 54de974..623ae6d 100644
--- a/src/src/functions.h
+++ b/src/src/functions.h
@@ -235,6 +235,7 @@ extern void msg_event_raise(const uschar *, const address_item *);
extern int exim_chown_failure(int, const uschar*, uid_t, gid_t);
extern const uschar * exim_errstr(int);
extern void exim_exit(int) NORETURN;
+extern void exim_gettimg(struct timeval *);
extern void exim_nullstd(void);
extern void exim_setugid(uid_t, gid_t, BOOL, uschar *);
extern void exim_underbar_exit(int) NORETURN;
diff --git a/src/src/receive.c b/src/src/receive.c
index df8719e..76b4d37 100644
--- a/src/src/receive.c
+++ b/src/src/receive.c
@@ -1784,7 +1784,7 @@ if (sender_host_address) dmarc_init(); /* initialize libopendmarc */
ids, and fractions of a second are required. See the comments that precede the
message id creation below. */
-(void)gettimeofday(&message_id_tv, NULL);
+exim_gettime(&message_id_tv);
/* For other uses of the received time we can operate with granularity of one
second, and for that we use the global variable received_time. This is for