clocks that go backwards.
Arguments:
- tgt_tv A timeval which was used to create uniqueness; its usec field
+ prev_tv A timeval which was used to create uniqueness; its usec field
has been rounded down to the value of the resolution.
We want to be sure the current time is greater than this.
+ On return, updated to current (rounded down).
resolution The resolution that was used to divide the microseconds
(1 for maildir, larger for message ids)
*/
void
-exim_wait_tick(struct timeval * tgt_tv, int resolution)
+exim_wait_tick(struct timeval * prev_tv, int resolution)
{
struct timeval now_tv;
long int now_true_usec;
now_true_usec = now_tv.tv_usec;
now_tv.tv_usec = (now_true_usec/resolution) * resolution;
-while (exim_tvcmp(&now_tv, tgt_tv) <= 0)
+while (exim_tvcmp(&now_tv, prev_tv) <= 0)
{
struct itimerval itval;
itval.it_interval.tv_sec = 0;
itval.it_interval.tv_usec = 0;
- itval.it_value.tv_sec = tgt_tv->tv_sec - now_tv.tv_sec;
- itval.it_value.tv_usec = tgt_tv->tv_usec + resolution - now_true_usec;
+ itval.it_value.tv_sec = prev_tv->tv_sec - now_tv.tv_sec;
+ itval.it_value.tv_usec = prev_tv->tv_usec + resolution - now_true_usec;
/* We know that, overall, "now" is less than or equal to "then". Therefore, a
negative value for the microseconds is possible only in the case when "now"
if (!f.running_in_test_harness)
{
debug_printf("tick check: " TIME_T_FMT ".%06lu " TIME_T_FMT ".%06lu\n",
- tgt_tv->tv_sec, (long) tgt_tv->tv_usec,
+ prev_tv->tv_sec, (long) prev_tv->tv_usec,
now_tv.tv_sec, (long) now_tv.tv_usec);
debug_printf("waiting " TIME_T_FMT ".%06lu sec\n",
itval.it_value.tv_sec, (long) itval.it_value.tv_usec);
now_true_usec = now_tv.tv_usec;
now_tv.tv_usec = (now_true_usec/resolution) * resolution;
}
+*prev_tv = now_tv;
}
? errors_sender_rc : EXIT_FAILURE;
int header_size = 256;
int start, end, domain;
-int id_resolution = 0;
int had_zero = 0;
int prevlines_length = 0;
+const int id_resolution = BASE_62 == 62 ? 5000 : 10000;
int ptr = 0;
uschar *timestamp;
int tslen;
+/* Time of creation of message_id */
+
+static struct timeval message_id_tv = { 0, 0 };
+
/* Release any open files that might have been cached while preparing to
accept the message - e.g. by verifying addresses - because reading a message
if (sender_host_address) dmarc_init(); /* initialize libopendmarc */
#endif
+/* In SMTP sessions we may receive several messages in one connection. Before
+each subsequent one, we wait for the clock to tick at the level of message-id
+granularity.
+This is so that the combination of time+pid is unique, even on systems where the
+pid can be re-used within our time interval. We can't shorten the interval
+without re-designing the message-id. See comments above where the message id is
+created. This is Something For The Future.
+Do this wait any time we have previously created a message-id, even if we
+rejected the message. This gives unique IDs for logging done by ACLs.
+The initial timestamp must have been obtained via exim_gettime() to avoid
+issues on Linux with suspend/resume. */
+
+if (message_id_tv.tv_sec)
+ {
+ message_id_tv.tv_usec = (message_id_tv.tv_usec/id_resolution) * id_resolution;
+ exim_wait_tick(&message_id_tv, id_resolution);
+ }
+
/* Remember the time of reception. Exim uses time+pid for uniqueness of message
ids, and fractions of a second are required. See the comments that precede the
message id creation below.
We use a routine that if possible uses a monotonic clock, and can be used again
after reception for the tick-wait even under the Linux non-Posix behaviour. */
-exim_gettime(&message_id_tv);
+else
+ 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
Ustrncpy(message_id + 7, string_base62((long int)getpid()), 6);
/* Deal with the case where the host number is set. The value of the number was
-checked when it was read, to ensure it isn't too big. The timing granularity is
-left in id_resolution so that an appropriate wait can be done after receiving
-the message, if necessary (we hope it won't be). */
+checked when it was read, to ensure it isn't too big. */
if (host_number_string)
- {
- id_resolution = BASE_62 == 62 ? 5000 : 10000;
sprintf(CS(message_id + MESSAGE_ID_LENGTH - 3), "-%2s",
string_base62((long int)(
host_number * (1000000/id_resolution) +
message_id_tv.tv_usec/id_resolution)) + 4);
- }
/* Host number not set: final field is just the fractional time at an
appropriate resolution. */
else
- {
- id_resolution = BASE_62 == 62 ? 500 : 1000;
sprintf(CS(message_id + MESSAGE_ID_LENGTH - 3), "-%2s",
string_base62((long int)(message_id_tv.tv_usec/id_resolution)) + 4);
- }
/* Add the current message id onto the current process info string if
it will fit. */
TIDYUP:
-/* In SMTP sessions we may receive several messages in one connection. After
-each one, we wait for the clock to tick at the level of message-id granularity.
-This is so that the combination of time+pid is unique, even on systems where the
-pid can be re-used within our time interval. We can't shorten the interval
-without re-designing the message-id. See comments above where the message id is
-created. This is Something For The Future.
-Do this wait any time we have created a message-id, even if we rejected the
-message. This gives unique IDs for logging done by ACLs.
-The initial timestamp must have been obtained via exim_gettime() to avoid
-issues on Linux with suspend/resume.
-It would be Nicer to only pause before a follow-on message. */
-
-if (id_resolution != 0)
- {
- message_id_tv.tv_usec = (message_id_tv.tv_usec/id_resolution) * id_resolution;
- exim_wait_tick(&message_id_tv, id_resolution);
- id_resolution = 0;
- }
-
-
process_info[process_info_len] = 0; /* Remove message id */
if (spool_data_file && cutthrough_done == NOT_TRIED)
{