diff options
| author | Paul Eggert | 2025-09-27 12:25:34 -0700 |
|---|---|---|
| committer | Paul Eggert | 2025-09-27 12:26:24 -0700 |
| commit | 50ab62ad75f939edd72a0aef7262f3f19ebb96dc (patch) | |
| tree | 55f1b5edce143aff25b0fdd8a4dc2fb89abd4031 /src/process.c | |
| parent | 5e06aa209bc906cf16f2e3de622a189bec34aa78 (diff) | |
| download | emacs-50ab62ad75f939edd72a0aef7262f3f19ebb96dc.tar.gz emacs-50ab62ad75f939edd72a0aef7262f3f19ebb96dc.zip | |
Use up-to-date time in wait_reading_process_output
In “Avoid duplicate calls to current_timespec” (2015-07-05)
we started caching current_timespec results in NOW.
However, this was buggy: we updated NOW only when the timeout was
nonzero, but the timeout can be set temporarily to zero in several
places in wait_reading_process_output (such as when checking for
process status changes), which would cause us to never update NOW
and therefore never detect that a timeout happened.
Also, this caching was wrong even in principle: since we call
Lisp code from wait_reading_process_output, substantial amounts
of time can pass, and we can be left using an outdated NOW and
incorrectly not time out. Also, nowadays we can use
monotonic_coarse_timespec which is fast, and which is better
anyway because it’s immune to manual clock changes.
Co-authored-by: Spencer Baugh <sbaugh@janestreet.com>
* src/process.c (wait_reading_process_output):
Stop caching the current realtime.
Instead, use the coarse monotonic clock without caching.
Diffstat (limited to 'src/process.c')
| -rw-r--r-- | src/process.c | 21 |
1 files changed, 6 insertions, 15 deletions
diff --git a/src/process.c b/src/process.c index 2804409f51e..8ec420aaa2c 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -5353,9 +5353,6 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 5353 | #endif | 5353 | #endif |
| 5354 | specpdl_ref count = SPECPDL_INDEX (); | 5354 | specpdl_ref count = SPECPDL_INDEX (); |
| 5355 | 5355 | ||
| 5356 | /* Close to the current time if known, an invalid timespec otherwise. */ | ||
| 5357 | struct timespec now = invalid_timespec (); | ||
| 5358 | |||
| 5359 | eassert (wait_proc == NULL | 5356 | eassert (wait_proc == NULL |
| 5360 | || NILP (wait_proc->thread) | 5357 | || NILP (wait_proc->thread) |
| 5361 | || XTHREAD (wait_proc->thread) == current_thread); | 5358 | || XTHREAD (wait_proc->thread) == current_thread); |
| @@ -5380,7 +5377,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 5380 | else if (time_limit > 0 || nsecs > 0) | 5377 | else if (time_limit > 0 || nsecs > 0) |
| 5381 | { | 5378 | { |
| 5382 | wait = TIMEOUT; | 5379 | wait = TIMEOUT; |
| 5383 | now = current_timespec (); | 5380 | struct timespec now = monotonic_coarse_timespec (); |
| 5384 | end_time = timespec_add (now, make_timespec (time_limit, nsecs)); | 5381 | end_time = timespec_add (now, make_timespec (time_limit, nsecs)); |
| 5385 | } | 5382 | } |
| 5386 | else | 5383 | else |
| @@ -5467,8 +5464,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 5467 | /* Exit if already run out. */ | 5464 | /* Exit if already run out. */ |
| 5468 | if (wait == TIMEOUT) | 5465 | if (wait == TIMEOUT) |
| 5469 | { | 5466 | { |
| 5470 | if (!timespec_valid_p (now)) | 5467 | struct timespec now = monotonic_coarse_timespec (); |
| 5471 | now = current_timespec (); | ||
| 5472 | if (timespec_cmp (end_time, now) <= 0) | 5468 | if (timespec_cmp (end_time, now) <= 0) |
| 5473 | break; | 5469 | break; |
| 5474 | timeout = timespec_sub (end_time, now); | 5470 | timeout = timespec_sub (end_time, now); |
| @@ -5721,8 +5717,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 5721 | && timespec_valid_p (timer_delay) | 5717 | && timespec_valid_p (timer_delay) |
| 5722 | && timespec_cmp (timer_delay, timeout) < 0) | 5718 | && timespec_cmp (timer_delay, timeout) < 0) |
| 5723 | { | 5719 | { |
| 5724 | if (!timespec_valid_p (now)) | 5720 | struct timespec now = monotonic_coarse_timespec (); |
| 5725 | now = current_timespec (); | ||
| 5726 | struct timespec timeout_abs = timespec_add (now, timeout); | 5721 | struct timespec timeout_abs = timespec_add (now, timeout); |
| 5727 | if (!timespec_valid_p (got_output_end_time) | 5722 | if (!timespec_valid_p (got_output_end_time) |
| 5728 | || timespec_cmp (timeout_abs, got_output_end_time) < 0) | 5723 | || timespec_cmp (timeout_abs, got_output_end_time) < 0) |
| @@ -5732,10 +5727,6 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 5732 | else | 5727 | else |
| 5733 | got_output_end_time = invalid_timespec (); | 5728 | got_output_end_time = invalid_timespec (); |
| 5734 | 5729 | ||
| 5735 | /* NOW can become inaccurate if time can pass during pselect. */ | ||
| 5736 | if (timeout.tv_sec > 0 || timeout.tv_nsec > 0) | ||
| 5737 | now = invalid_timespec (); | ||
| 5738 | |||
| 5739 | #if defined HAVE_GETADDRINFO_A || defined HAVE_GNUTLS | 5730 | #if defined HAVE_GETADDRINFO_A || defined HAVE_GNUTLS |
| 5740 | if (retry_for_async | 5731 | if (retry_for_async |
| 5741 | && (timeout.tv_sec > 0 || timeout.tv_nsec > ASYNC_RETRY_NSEC)) | 5732 | && (timeout.tv_sec > 0 || timeout.tv_nsec > ASYNC_RETRY_NSEC)) |
| @@ -5873,7 +5864,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 5873 | } | 5864 | } |
| 5874 | if (timespec_cmp (cmp_time, huge_timespec) < 0) | 5865 | if (timespec_cmp (cmp_time, huge_timespec) < 0) |
| 5875 | { | 5866 | { |
| 5876 | now = current_timespec (); | 5867 | struct timespec now = monotonic_coarse_timespec (); |
| 5877 | if (timespec_cmp (cmp_time, now) <= 0) | 5868 | if (timespec_cmp (cmp_time, now) <= 0) |
| 5878 | break; | 5869 | break; |
| 5879 | } | 5870 | } |
| @@ -8132,7 +8123,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 8132 | else if (time_limit > 0 || nsecs > 0) | 8123 | else if (time_limit > 0 || nsecs > 0) |
| 8133 | { | 8124 | { |
| 8134 | wait = TIMEOUT; | 8125 | wait = TIMEOUT; |
| 8135 | end_time = timespec_add (current_timespec (), | 8126 | end_time = timespec_add (monotonic_coarse_timespec (), |
| 8136 | make_timespec (time_limit, nsecs)); | 8127 | make_timespec (time_limit, nsecs)); |
| 8137 | } | 8128 | } |
| 8138 | else | 8129 | else |
| @@ -8164,7 +8155,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 8164 | /* Exit if already run out. */ | 8155 | /* Exit if already run out. */ |
| 8165 | if (wait == TIMEOUT) | 8156 | if (wait == TIMEOUT) |
| 8166 | { | 8157 | { |
| 8167 | struct timespec now = current_timespec (); | 8158 | struct timespec now = monotonic_coarse_timespec (); |
| 8168 | if (timespec_cmp (end_time, now) <= 0) | 8159 | if (timespec_cmp (end_time, now) <= 0) |
| 8169 | break; | 8160 | break; |
| 8170 | timeout = timespec_sub (end_time, now); | 8161 | timeout = timespec_sub (end_time, now); |