Subject: bug#6074: accept-process-output on listening sockets cause non-interruptible infloop

From: Pip Cet <[email-masked]>
Date: Mon, 22 Jul 2019 03:52:33 +0000

> With this code Emacs seems to be stuck in an endless loop and is not
> incorruptible with C-g:

> (let ((proc (make-network-process :name "foo" :server t :noquery t
>  :family 'local :service "/tmp/foo.socket")))
>   (accept-process-output proc))

On Linux, the problem appears to be that we don't abort this infloop
in process.c if a read () returns EINVAL:

          while (true)
        {
          int nread = read_process_output (proc, wait_proc->infd);
          if (nread < 0)
            {
              if (errno == EIO || would_block (errno))
            break;
            }
          else
            {
              if (got_some_output < nread)
            got_some_output = nread;
              if (nread == 0)
            break;
              read_some_bytes = true;
            }
        }

That seems problematic to me, since we might get non-EIO errors for
other reasons. I'm attaching a patch that appears to fix the issue.
From ad294bb1e7ff7012dca3345a8ca2046e0f9dc8fb Mon Sep 17 00:00:00 2001
From: Pip Cet <[email-masked]>
Date: Mon, 22 Jul 2019 03:49:54 +0000
Subject: [PATCH] Don't retry reading after receiving EINVAL (bug#6074)

* src/process.c (wait_reading_process_output): Don't retry reading
from an fd after an unknown error.
---
 src/process.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/process.c b/src/process.c
index abadabe77e..1311409274 100644
--- a/src/process.c
+++ b/src/process.c
@@ -5277,7 +5277,9 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
 		  int nread = read_process_output (proc, wait_proc->infd);
 		  if (nread < 0)
 		    {
-		      if (errno == EIO || would_block (errno))
+		      if (errno == EINTR)
+			continue;
+		      else
 			break;
 		    }
 		  else
-- 
2.22.0