aboutsummaryrefslogtreecommitdiffstats
path: root/src/process.c
diff options
context:
space:
mode:
authorPaul Eggert2025-09-27 12:25:34 -0700
committerPaul Eggert2025-09-27 12:26:24 -0700
commit50ab62ad75f939edd72a0aef7262f3f19ebb96dc (patch)
tree55f1b5edce143aff25b0fdd8a4dc2fb89abd4031 /src/process.c
parent5e06aa209bc906cf16f2e3de622a189bec34aa78 (diff)
downloademacs-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.c21
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);