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

From: Helmut Eller <[email-masked]>
Date: Wed, 13 Oct 2021 15:39:30 +0200

On Wed, Oct 13 2021, Lars Ingebrigtsen wrote:

> Helmut Eller <[email-masked]> writes:
>
>> I would like to request this feature: stop-process, when called with a
>> sub-process that is connected via pipes, should use delete_read_fd.  It
>> should basically do the same as for sockets.
>>
>> Currently, stop-process uses some difficult to understand logic and
>> eventually sends SIGSTOP to the process.  This might work in theory, but
>> in practice it can take a long time before Emacs stops receiving output.
>
> You're supposed to be able to use `continue-process' on the process
> after stopping it for a while -- that's not possible if you delete the
> fd.  

Here "deleting" only removes the fd from the event loop; it doesn't
close the fd.  The fd can be added back by `continue-process'.

The patch below implements the basic idea.  Though, not very nicely
because in this case p->command can't be used to indicate that the fd is
temporarily "deleted".  It writes something to the process->plist.  A
proper patch would probably do this in a better way:

diff --git a/src/process.c b/src/process.c
index 746cdc0428..5b833187d5 100644
--- a/src/process.c
+++ b/src/process.c
@@ -6921,15 +6921,26 @@ of incoming traffic.  */)
   (Lisp_Object process, Lisp_Object current_group)
 {
   if (PROCESSP (process) && (NETCONN_P (process) || SERIALCONN_P (process)
-			     || PIPECONN_P (process)))
+			     || PIPECONN_P (process)
+			     || (EQ (Fprocess_type (process), Qreal)
+				 && NILP (Fprocess_tty_name (process)))))
     {
       struct Lisp_Process *p;
 
       p = XPROCESS (process);
-      if (NILP (p->command)
+      if ((NILP (p->command)
+	   || (EQ (Fprocess_type (process), Qreal)
+	       && NILP (Fprocess_tty_name (process))))
 	  && p->infd >= 0)
 	delete_read_fd (p->infd);
-      pset_command (p, Qt);
+
+      if (NILP (p->command))
+	pset_command (p, Qt);
+      else if (EQ (Fprocess_type (process), Qreal)
+	       && NILP (Fprocess_tty_name (process)))
+	Fset_process_plist (process,
+			    Fplist_put (Fprocess_plist (process),
+					Qstop, Qt));
       return process;
     }
 #ifndef SIGTSTP
@@ -6948,13 +6959,18 @@ traffic.  */)
   (Lisp_Object process, Lisp_Object current_group)
 {
   if (PROCESSP (process) && (NETCONN_P (process) || SERIALCONN_P (process)
-			     || PIPECONN_P (process)))
+			     || PIPECONN_P (process)
+			     || (EQ (Fprocess_type (process), Qreal)
+				 && NILP (Fprocess_tty_name (process)))))
     {
       struct Lisp_Process *p;
 
       p = XPROCESS (process);
       eassert (p->infd < FD_SETSIZE);
-      if (EQ (p->command, Qt)
+      if ((EQ (p->command, Qt)
+	   || (EQ (Fprocess_type (process), Qreal)
+	       && NILP (Fprocess_tty_name (process))
+	       && EQ (Fplist_get (Fprocess_plist (process), Qstop), Qt)))
 	  && p->infd >= 0
 	  && (!EQ (p->filter, Qt) || EQ (p->status, Qlisten)))
 	{
@@ -6966,7 +6982,14 @@ traffic.  */)
 	  tcflush (p->infd, TCIFLUSH);
 #endif /* not WINDOWSNT */
 	}
-      pset_command (p, Qnil);
+      if (EQ (p->command, Qt))
+	pset_command (p, Qnil);
+      else if (EQ (Fprocess_type (process), Qreal)
+	       && NILP (Fprocess_tty_name (process))
+	       && EQ (Fplist_get (Fprocess_plist (process), Qstop), Qt))
+	Fset_process_plist (process,
+			    Fplist_put (Fprocess_plist (process),
+					Qstop, Qnil));
       return process;
     }
 #ifdef SIGCONT

Helmut