aboutsummaryrefslogtreecommitdiffstats
path: root/src/process.c
diff options
context:
space:
mode:
authorMatthias Dahl2018-02-16 17:57:40 +0200
committerEli Zaretskii2018-06-02 12:13:12 +0300
commitde69d28458e52487ebb9db47b100c23a16ab6093 (patch)
tree9938cebe8d4d215ca8a86570b7f5e2976307f209 /src/process.c
parent76f692e82f13dc2d36e3636932f3998023a66289 (diff)
downloademacs-de69d28458e52487ebb9db47b100c23a16ab6093.tar.gz
emacs-de69d28458e52487ebb9db47b100c23a16ab6093.zip
Fix wait_reading_process_output wait_proc hang
* src/process.c (read_process_output): Track bytes read from a process. (wait_reading_process_output): If called recursively through timers and/or process filters via accept-process-output, it is possible that the output of wait_proc has already been read by one of those recursive calls, leaving the original call hanging forever if no further output arrives through that fd and no timeout has been set. Fix that by using the process read accounting to keep track of how many bytes have been read and use that as a condition to break out of the infinite loop and return to the caller as well as to calculate the proper return value (if a wait_proc is given that is). * src/process.h (struct Lisp_Process): Add nbytes_read to track bytes read from a process. (cherry picked from commit 4ba32858d61eee16f17b51aca01c15211a0912f8)
Diffstat (limited to 'src/process.c')
-rw-r--r--src/process.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/src/process.c b/src/process.c
index 45ab1fd7245..7f6ea1261e7 100644
--- a/src/process.c
+++ b/src/process.c
@@ -5009,6 +5009,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
5009 struct timespec got_output_end_time = invalid_timespec (); 5009 struct timespec got_output_end_time = invalid_timespec ();
5010 enum { MINIMUM = -1, TIMEOUT, INFINITY } wait; 5010 enum { MINIMUM = -1, TIMEOUT, INFINITY } wait;
5011 int got_some_output = -1; 5011 int got_some_output = -1;
5012 uintmax_t prev_wait_proc_nbytes_read = wait_proc ? wait_proc->nbytes_read : 0;
5012#if defined HAVE_GETADDRINFO_A || defined HAVE_GNUTLS 5013#if defined HAVE_GETADDRINFO_A || defined HAVE_GNUTLS
5013 bool retry_for_async; 5014 bool retry_for_async;
5014#endif 5015#endif
@@ -5463,6 +5464,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
5463 if (nfds == 0) 5464 if (nfds == 0)
5464 { 5465 {
5465 /* Exit the main loop if we've passed the requested timeout, 5466 /* Exit the main loop if we've passed the requested timeout,
5467 or have read some bytes from our wait_proc (either directly
5468 in this call or indirectly through timers / process filters),
5466 or aren't skipping processes and got some output and 5469 or aren't skipping processes and got some output and
5467 haven't lowered our timeout due to timers or SIGIO and 5470 haven't lowered our timeout due to timers or SIGIO and
5468 have waited a long amount of time due to repeated 5471 have waited a long amount of time due to repeated
@@ -5470,7 +5473,9 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
5470 struct timespec huge_timespec 5473 struct timespec huge_timespec
5471 = make_timespec (TYPE_MAXIMUM (time_t), 2 * TIMESPEC_RESOLUTION); 5474 = make_timespec (TYPE_MAXIMUM (time_t), 2 * TIMESPEC_RESOLUTION);
5472 struct timespec cmp_time = huge_timespec; 5475 struct timespec cmp_time = huge_timespec;
5473 if (wait < TIMEOUT) 5476 if (wait < TIMEOUT
5477 || (wait_proc
5478 && wait_proc->nbytes_read != prev_wait_proc_nbytes_read))
5474 break; 5479 break;
5475 if (wait == TIMEOUT) 5480 if (wait == TIMEOUT)
5476 cmp_time = end_time; 5481 cmp_time = end_time;
@@ -5785,6 +5790,15 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
5785 maybe_quit (); 5790 maybe_quit ();
5786 } 5791 }
5787 5792
5793 /* Timers and/or process filters that we have run could have themselves called
5794 `accept-process-output' (and by that indirectly this function), thus
5795 possibly reading some (or all) output of wait_proc without us noticing it.
5796 This could potentially lead to an endless wait (dealt with earlier in the
5797 function) and/or a wrong return value (dealt with here). */
5798 if (wait_proc && wait_proc->nbytes_read != prev_wait_proc_nbytes_read)
5799 got_some_output = min (INT_MAX, (wait_proc->nbytes_read
5800 - prev_wait_proc_nbytes_read));
5801
5788 return got_some_output; 5802 return got_some_output;
5789} 5803}
5790 5804
@@ -5903,6 +5917,9 @@ read_process_output (Lisp_Object proc, int channel)
5903 coding->mode |= CODING_MODE_LAST_BLOCK; 5917 coding->mode |= CODING_MODE_LAST_BLOCK;
5904 } 5918 }
5905 5919
5920 /* Ignore carryover, it's been added by a previous iteration already. */
5921 p->nbytes_read += nbytes;
5922
5906 /* Now set NBYTES how many bytes we must decode. */ 5923 /* Now set NBYTES how many bytes we must decode. */
5907 nbytes += carryover; 5924 nbytes += carryover;
5908 5925