Package: emacs;
Reported by: Ian Kelling <ian <at> iankelling.org>
Date: Sat, 4 Jul 2015 12:35:02 UTC
Severity: normal
Tags: patch
Found in version 25.0.50
Done: Paul Eggert <eggert <at> cs.ucla.edu>
Bug is archived. No further changes may be made.
View this message in rfc822 format
From: Ian Kelling <ian <at> iankelling.org> To: 20978 <at> debbugs.gnu.org Subject: bug#20978: [PATCH 6/7] Don't return as fast reading any process output Date: Sat, 04 Jul 2015 05:47:07 -0700
* src/process.c (wait_reading_process_output): The patch for debbugs:17647 returns too fast sometimes when reading from any processes. Revert part of it, and limit the timeout more sensibly. diff --git a/src/process.c b/src/process.c index 538455c..cb48e5f 100644 --- a/src/process.c +++ b/src/process.c @@ -4585,7 +4585,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, bool no_avail; int xerrno; Lisp_Object proc; - struct timespec timeout, end_time; + struct timespec timeout, end_time, timer_delay; + struct timespec got_output_end_time = invalid_timespec (); enum { MINIMUM, TIMEOUT, INFINITY } wait; int got_some_output = -1; ptrdiff_t count = SPECPDL_INDEX (); @@ -4618,7 +4619,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, while (1) { - bool timeout_reduced_for_timers = false; + bool process_skipped = false; /* If calling from keyboard input, do not quit since we want to return C-g as an input character. @@ -4632,10 +4633,6 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, if (! NILP (wait_for_cell) && ! NILP (XCAR (wait_for_cell))) break; - /* After reading input, vacuum up any leftovers without waiting. */ - if (0 <= got_some_output) - wait = MINIMUM; - /* Compute time from now till when time limit is up. */ /* Exit if already run out. */ if (wait == MINIMUM) @@ -4661,8 +4658,6 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, if (NILP (wait_for_cell) && just_wait_proc >= 0) { - struct timespec timer_delay; - do { unsigned old_timers_run = timers_run; @@ -4693,19 +4688,9 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, && requeued_events_pending_p ()) break; - if (timespec_valid_p (timer_delay)) - { - if (timespec_cmp (timer_delay, timeout) < 0) - { - timeout = timer_delay; - timeout_reduced_for_timers = true; - } - } - else - { - /* This is so a breakpoint can be put here. */ + /* This is so a breakpoint can be put here. */ + if (!timespec_valid_p (timer_delay)) wait_reading_process_output_1 (); - } } /* Cause C-g and alarm signals to take immediate action, @@ -4875,6 +4860,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, if (!XPROCESS (proc)->read_output_skip) continue; FD_CLR (channel, &Available); + process_skipped = true; XPROCESS (proc)->read_output_skip = 0; if (XPROCESS (proc)->read_output_delay < adaptive_nsecs) adaptive_nsecs = XPROCESS (proc)->read_output_delay; @@ -4884,6 +4870,30 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, process_output_skip = 0; } + /* If we've got some output and haven't limited our timeout + * with adaptive read buffering, limit it. */ + if (got_some_output > 0 && !process_skipped + && (timeout.tv_sec + || timeout.tv_nsec > READ_OUTPUT_DELAY_INCREMENT)) + timeout = make_timespec (0, READ_OUTPUT_DELAY_INCREMENT); + + + if (NILP (wait_for_cell) && just_wait_proc >= 0 + && timespec_valid_p (timer_delay) + && timespec_cmp (timer_delay, timeout) < 0) + { + struct timespec timeout_abs = timespec_add (current_timespec (), + timeout); + if (!timespec_valid_p (got_output_end_time) + || timespec_cmp (timeout_abs, + got_output_end_time) < 0) + got_output_end_time = timeout_abs; + timeout = timer_delay; + } + else + got_output_end_time = invalid_timespec (); + + #if defined (HAVE_NS) nfds = ns_select #elif defined (HAVE_GLIB) @@ -4955,9 +4965,17 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, /* If we woke up due to SIGWINCH, actually change size now. */ do_pending_window_change (0); - if (wait != INFINITY && nfds == 0 && ! timeout_reduced_for_timers) - /* We waited the full specified time, so return now. */ - break; + if (nfds == 0) + { + struct timespec now = current_timespec (); + if ((timeout.tv_sec == 0 && timeout.tv_nsec == 0) + || (wait == TIMEOUT && timespec_cmp (end_time, now) <= 0) + || (!process_skipped && got_some_output > 0 + && (!timespec_valid_p (got_output_end_time) + || timespec_cmp (got_output_end_time, now) <= 0))) + break; + } + if (nfds < 0) { if (xerrno == EINTR) @@ -5084,6 +5102,9 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, got_some_output = nread; if (nread > 0) { + /* vacuum up any leftovers without waiting. */ + if (wait_proc == XPROCESS (proc)) + wait = MINIMUM; /* Since read_process_output can run a filter, which can call accept-process-output, don't try to read from any other processes -- 2.4.5
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.