[exim-cvs] Fix message-reception clock usage. Bug 2615

Top Page
Delete this message
Reply to this message
Author: Exim Git Commits Mailing List
Date:  
To: exim-cvs
Subject: [exim-cvs] Fix message-reception clock usage. Bug 2615
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