Subject: bug#51177: 29.0.50; stop-process on pipes

From: Helmut Eller <[email-masked]>
Date: Fri, 12 Nov 2021 06:13:42 +0100

On Fri, Nov 12 2021, Lars Ingebrigtsen wrote:

>> However, I would like to propose
>> that, in status_notify, the sentinel function should be called before
>> closing the file descriptors.  That way, the sentinel can read the
>> buffered output as suggested in the example.
>
> A sentinel usually doesn't read anything...

The idea is that the sentinel does something like this:

  (lambda (p _)
    (set-process-filter p filter)
    (while (accept-process-output p 0)))

First, it changes the filter from t to an actual function.  Then it
calls accept-process-output.  This in turn polls the file descriptors
and calls the filter function if there is buffered output.  If there is
no buffered output to read, then accept-process-output returns nil and
the while loop terminates.

All this happens after the process has terminated.  Granted, not a
particularly intuitive API.

However, the required change would be rather small, I think.  The patch
below shows how this could be done.  It basically moves the part that
closes the file descriptors after the call to exec_sentinel.

diff --git a/src/process.c b/src/process.c
index f923aff1cb..bc236c7e4c 100644
--- a/src/process.c
+++ b/src/process.c
@@ -1341,6 +1341,9 @@ The string argument is normally a multibyte string, except:
                && !EQ (p->command, Qt))
         add_process_read_fd (p->infd);
     }
+  else {
+    fprintf (stderr, "p->infd < 0 in Fset_process_filter\n");
+  }
 
   pset_filter (p, filter);
 
@@ -7536,15 +7539,6 @@ status_notify (struct Lisp_Process *deleting_process,
 	  if (CONSP (p->status))
 	    symbol = XCAR (p->status);
 
-	  if (EQ (symbol, Qsignal) || EQ (symbol, Qexit)
-	      || EQ (symbol, Qclosed))
-	    {
-	      if (delete_exited_processes)
-		remove_process (proc);
-	      else
-		deactivate_process (proc);
-	    }
-
 	  /* The actions above may have further incremented p->tick.
 	     So set p->update_tick again so that an error in the sentinel will
 	     not cause this code to be run again.  */
@@ -7554,6 +7548,16 @@ status_notify (struct Lisp_Process *deleting_process,
 	  if (BUFFERP (p->buffer))
 	    /* In case it uses %s in mode-line-format.  */
 	    bset_update_mode_line (XBUFFER (p->buffer));
+
+	  if (EQ (symbol, Qsignal) || EQ (symbol, Qexit)
+	      || EQ (symbol, Qclosed))
+	    {
+	      if (delete_exited_processes)
+		remove_process (proc);
+	      else
+		deactivate_process (proc);
+	    }
+
 	}
     } /* end for */