1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-06 06:20:55 -08:00

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.
This commit is contained in:
Paul Eggert 2025-09-27 12:25:34 -07:00
parent 5e06aa209b
commit 50ab62ad75

View file

@ -5353,9 +5353,6 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
#endif
specpdl_ref count = SPECPDL_INDEX ();
/* Close to the current time if known, an invalid timespec otherwise. */
struct timespec now = invalid_timespec ();
eassert (wait_proc == NULL
|| NILP (wait_proc->thread)
|| XTHREAD (wait_proc->thread) == current_thread);
@ -5380,7 +5377,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
else if (time_limit > 0 || nsecs > 0)
{
wait = TIMEOUT;
now = current_timespec ();
struct timespec now = monotonic_coarse_timespec ();
end_time = timespec_add (now, make_timespec (time_limit, nsecs));
}
else
@ -5467,8 +5464,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
/* Exit if already run out. */
if (wait == TIMEOUT)
{
if (!timespec_valid_p (now))
now = current_timespec ();
struct timespec now = monotonic_coarse_timespec ();
if (timespec_cmp (end_time, now) <= 0)
break;
timeout = timespec_sub (end_time, now);
@ -5721,8 +5717,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
&& timespec_valid_p (timer_delay)
&& timespec_cmp (timer_delay, timeout) < 0)
{
if (!timespec_valid_p (now))
now = current_timespec ();
struct timespec now = monotonic_coarse_timespec ();
struct timespec timeout_abs = timespec_add (now, timeout);
if (!timespec_valid_p (got_output_end_time)
|| 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,
else
got_output_end_time = invalid_timespec ();
/* NOW can become inaccurate if time can pass during pselect. */
if (timeout.tv_sec > 0 || timeout.tv_nsec > 0)
now = invalid_timespec ();
#if defined HAVE_GETADDRINFO_A || defined HAVE_GNUTLS
if (retry_for_async
&& (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,
}
if (timespec_cmp (cmp_time, huge_timespec) < 0)
{
now = current_timespec ();
struct timespec now = monotonic_coarse_timespec ();
if (timespec_cmp (cmp_time, now) <= 0)
break;
}
@ -8132,7 +8123,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
else if (time_limit > 0 || nsecs > 0)
{
wait = TIMEOUT;
end_time = timespec_add (current_timespec (),
end_time = timespec_add (monotonic_coarse_timespec (),
make_timespec (time_limit, nsecs));
}
else
@ -8164,7 +8155,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
/* Exit if already run out. */
if (wait == TIMEOUT)
{
struct timespec now = current_timespec ();
struct timespec now = monotonic_coarse_timespec ();
if (timespec_cmp (end_time, now) <= 0)
break;
timeout = timespec_sub (end_time, now);