unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#51177: 29.0.50; stop-process on pipes
@ 2021-10-13  9:20 Helmut Eller
  2021-10-13 11:45 ` Lars Ingebrigtsen
                   ` (2 more replies)
  0 siblings, 3 replies; 23+ messages in thread
From: Helmut Eller @ 2021-10-13  9:20 UTC (permalink / raw)
  To: 51177


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.

The code below illustrates the problem with two examples:
test-stop-process and test-signal-process.  One uses stop-process while
the other uses (signal-process 'SIGSTOP).  The output is something like
this:

  emacs -Q --batch -l stop.el -f ert-run-tests-batch-and-exit
  Running 2 tests (2021-10-13 11:00:45+0200, selector ‘t’)
  use-signals = t; my-counter = 17 buffer-size = 69672
     passed  1/2  test-signal-process (0.200925 sec)
  use-signals = nil; my-counter = 1099 buffer-size = 4501504
     passed  2/2  test-stop-process (0.201133 sec)

With signal-process, the filter function is called 17 times before the
sub-process stops sending output.

With stop-process, it takes 1099 calls and Emacs receives 4 megabytes of
output.  These numbers can be even higher, if the argument to sleep-for
is larger.

If we would use delete_read_fd, then the filter function would be called
exactly once.  At least I think so.  That would, of course, be much more
desirable.

Helmut


(ert-deftest test-stop-process () (run-test nil))

(ert-deftest test-signal-process () (run-test t))

(defun my-start-process ()
  (let ((buffer (generate-new-buffer " some-process")))
    (make-process :command '("cat" "/dev/zero")
                  :name (buffer-name buffer)
                  :buffer buffer
                  :filter #'my-filter
                  :connection-type 'pipe)))

(defvar my-counter 0)

(defun my-filter (proc string)
  (setq my-counter (1+ my-counter))
  (with-current-buffer (process-buffer proc)
    (goto-char (point-max))
    (insert string)
    ;; (message "stopping: %s %s %s" (buffer-size)
    ;;         (process-id proc) (process-status proc))
    (cond ((process-get proc 'use-signals)
           (signal-process proc 'SIGSTOP))
          (t
           (stop-process proc)))))

(defun run-test (use-signals)
  (let ((proc (my-start-process))
        (my-counter 0))
    (process-put proc 'use-signals use-signals)
    (sleep-for 0.2)
    (while (= my-counter 0)
      (accept-process-output p 0.1))
    (message "use-signals = %s; my-counter = %s buffer-size = %s" 
             use-signals my-counter
             (buffer-size (process-buffer proc)))))



In GNU Emacs 29.0.50 (build 3, x86_64-pc-linux-gnu, GTK+ Version 3.24.24, cairo version 1.16.0)
 of 2021-10-11 built on caladan
Repository revision: 2810fe6bfca182e4376d818b5510507d5ff7e1b5
Repository branch: master
Windowing system distributor 'The X.Org Foundation', version 11.0.12011000
System Description: Debian GNU/Linux 11 (bullseye)

Configured using:
 'configure --with-xpm=ifavailable --with-jpeg=ifavailable
 --with-gif=ifavailable --with-tiff=ifavailable'

Configured features:
CAIRO DBUS FREETYPE GLIB GMP GNUTLS GSETTINGS HARFBUZZ LIBSELINUX
LIBSYSTEMD LIBXML2 MODULES NOTIFY INOTIFY PDUMPER PNG SECCOMP SOUND
THREADS TOOLKIT_SCROLL_BARS X11 XDBE XIM GTK3 ZLIB

Important settings:
  value of $LANG: C.UTF-8
  locale-coding-system: utf-8-unix





^ permalink raw reply	[flat|nested] 23+ messages in thread

* bug#51177: 29.0.50; stop-process on pipes
  2021-10-13  9:20 bug#51177: 29.0.50; stop-process on pipes Helmut Eller
@ 2021-10-13 11:45 ` Lars Ingebrigtsen
  2021-10-13 13:39   ` Helmut Eller
  2021-10-13 13:01 ` Eli Zaretskii
  2021-11-11 19:47 ` Helmut Eller
  2 siblings, 1 reply; 23+ messages in thread
From: Lars Ingebrigtsen @ 2021-10-13 11:45 UTC (permalink / raw)
  To: Helmut Eller; +Cc: 51177

Helmut Eller <eller.helmut@gmail.com> 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.  

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





^ permalink raw reply	[flat|nested] 23+ messages in thread

* bug#51177: 29.0.50; stop-process on pipes
  2021-10-13  9:20 bug#51177: 29.0.50; stop-process on pipes Helmut Eller
  2021-10-13 11:45 ` Lars Ingebrigtsen
@ 2021-10-13 13:01 ` Eli Zaretskii
  2021-10-13 14:04   ` Helmut Eller
  2021-11-11 19:47 ` Helmut Eller
  2 siblings, 1 reply; 23+ messages in thread
From: Eli Zaretskii @ 2021-10-13 13:01 UTC (permalink / raw)
  To: Helmut Eller; +Cc: 51177

> From: Helmut Eller <eller.helmut@gmail.com>
> Date: Wed, 13 Oct 2021 11:20:01 +0200
> 
> 
> 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.

Unlike with sockets, we are talking about a real sub-process on the
other end of the pipe, and it will now get SIGPIPE.  Are we sure this
is OK? perhaps it will interfere with the process's cleanup when it
receives a signal?

If there's any real possibility this could change behavior, I think we
should make such behavior optional.





^ permalink raw reply	[flat|nested] 23+ messages in thread

* bug#51177: 29.0.50; stop-process on pipes
  2021-10-13 11:45 ` Lars Ingebrigtsen
@ 2021-10-13 13:39   ` Helmut Eller
  0 siblings, 0 replies; 23+ messages in thread
From: Helmut Eller @ 2021-10-13 13:39 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: 51177

[-- Attachment #1: Type: text/plain, Size: 1071 bytes --]

On Wed, Oct 13 2021, Lars Ingebrigtsen wrote:

> Helmut Eller <eller.helmut@gmail.com> 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:


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: stop.patch --]
[-- Type: text/x-diff, Size: 2313 bytes --]

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

[-- Attachment #3: Type: text/plain, Size: 8 bytes --]


Helmut

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* bug#51177: 29.0.50; stop-process on pipes
  2021-10-13 13:01 ` Eli Zaretskii
@ 2021-10-13 14:04   ` Helmut Eller
  2021-10-14  7:51     ` jakanakaevangeli
  0 siblings, 1 reply; 23+ messages in thread
From: Helmut Eller @ 2021-10-13 14:04 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 51177

On Wed, Oct 13 2021, Eli Zaretskii wrote:

>> From: Helmut Eller <eller.helmut@gmail.com>
>> Date: Wed, 13 Oct 2021 11:20:01 +0200
>> 
>> 
>> 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.
>
> Unlike with sockets, we are talking about a real sub-process on the
> other end of the pipe, and it will now get SIGPIPE.  Are we sure this
> is OK? perhaps it will interfere with the process's cleanup when it
> receives a signal?

A valid concern, yes.

> If there's any real possibility this could change behavior, I think we
> should make such behavior optional.

Maybe we could add a pair of functions that exposes delete_read_fd and
add_process_read_fd more directly.

Helmut






^ permalink raw reply	[flat|nested] 23+ messages in thread

* bug#51177: 29.0.50; stop-process on pipes
  2021-10-13 14:04   ` Helmut Eller
@ 2021-10-14  7:51     ` jakanakaevangeli
  2021-10-14  8:00       ` Helmut Eller
  0 siblings, 1 reply; 23+ messages in thread
From: jakanakaevangeli @ 2021-10-14  7:51 UTC (permalink / raw)
  To: Helmut Eller, Eli Zaretskii; +Cc: 51177

Helmut Eller <eller.helmut@gmail.com> writes:

> On Wed, Oct 13 2021, Eli Zaretskii wrote:
>
>>> From: Helmut Eller <eller.helmut@gmail.com>
>>> Date: Wed, 13 Oct 2021 11:20:01 +0200
>>> 
>>> 
>>> 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.
>>
>> Unlike with sockets, we are talking about a real sub-process on the
>> other end of the pipe, and it will now get SIGPIPE.  Are we sure this
>> is OK? perhaps it will interfere with the process's cleanup when it
>> receives a signal?
>
> A valid concern, yes.
>
>> If there's any real possibility this could change behavior, I think we
>> should make such behavior optional.
>
> Maybe we could add a pair of functions that exposes delete_read_fd and
> add_process_read_fd more directly.
>
> Helmut

I haven't read you request and patch in detail, but have you tried
"(set-process-filter proc t)"?  Looking at the doc string of
set-process-filter and reading its code suggests that this may be what
you want.

Best regards.





^ permalink raw reply	[flat|nested] 23+ messages in thread

* bug#51177: 29.0.50; stop-process on pipes
  2021-10-14  7:51     ` jakanakaevangeli
@ 2021-10-14  8:00       ` Helmut Eller
  2021-10-14 11:10         ` Lars Ingebrigtsen
  0 siblings, 1 reply; 23+ messages in thread
From: Helmut Eller @ 2021-10-14  8:00 UTC (permalink / raw)
  To: jakanakaevangeli; +Cc: 51177

On Thu, Oct 14 2021, jakanakaevangeli@chiru.no wrote:

> I haven't read you request and patch in detail, but have you tried
> "(set-process-filter proc t)"?  Looking at the doc string of
> set-process-filter and reading its code suggests that this may be what
> you want.

Indeed, this does exactly what I want.  Thank you!

I did not read the docstring but I did read the manual.  This feature is
not described in the manual.  At least not near set-process-filter.

Helmut





^ permalink raw reply	[flat|nested] 23+ messages in thread

* bug#51177: 29.0.50; stop-process on pipes
  2021-10-14  8:00       ` Helmut Eller
@ 2021-10-14 11:10         ` Lars Ingebrigtsen
  2021-10-16 16:24           ` Helmut Eller
  0 siblings, 1 reply; 23+ messages in thread
From: Lars Ingebrigtsen @ 2021-10-14 11:10 UTC (permalink / raw)
  To: Helmut Eller; +Cc: 51177, jakanakaevangeli

Helmut Eller <eller.helmut@gmail.com> writes:

> I did not read the docstring but I did read the manual.  This feature is
> not described in the manual.  At least not near set-process-filter.

Yup.  I've now documented the t value in the manual in emacs-28.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





^ permalink raw reply	[flat|nested] 23+ messages in thread

* bug#51177: 29.0.50; stop-process on pipes
  2021-10-14 11:10         ` Lars Ingebrigtsen
@ 2021-10-16 16:24           ` Helmut Eller
  2021-10-16 16:47             ` Eli Zaretskii
  0 siblings, 1 reply; 23+ messages in thread
From: Helmut Eller @ 2021-10-16 16:24 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: 51177, jakanakaevangeli

On Thu, Oct 14 2021, Lars Ingebrigtsen wrote:

> Helmut Eller <eller.helmut@gmail.com> writes:
>
>> I did not read the docstring but I did read the manual.  This feature is
>> not described in the manual.  At least not near set-process-filter.
>
> Yup.  I've now documented the t value in the manual in emacs-28.

The t value also doesn't seem be handled correctly by make-process:

(ert-deftest test-filter=t ()
  (let ((p (make-process :command '("dd" "if=/dev/zero" "count=0")
			 :name "foo"
			 :filter t)))
    ;;(set-process-filter p t)
    (while (eq (process-status p) 'run)
      (accept-process-output p))))

when executed with

  emacs -Q --batch -l test.el -f ert-run-tests-batch-and-exit

produces:

Running 1 tests (2021-10-16 18:21:53+0200, selector ‘t’)
Test test-filter=t backtrace:
  t(#<process foo> "0+0 records in\n0+0 records out\n")
  accept-process-output(#<process foo>)
  (while (eq (process-status p) 'run) (accept-process-output p))
  (let ((p (make-process :command '("dd" "if=/dev/zero" "count=0") :na
  (lambda nil (let ((p (make-process :command '("dd" "if=/dev/zero" "c
  ert--run-test-internal(#s(ert--test-execution-info :test #s(ert-test
  ert-run-test(#s(ert-test :name test-filter=t :documentation nil :bod
  ert-run-or-rerun-test(#s(ert--stats :selector t :tests [#s(ert-test 
  ert-run-tests(t #f(compiled-function (event-type &rest event-args) #
  ert-run-tests-batch(nil)
  ert-run-tests-batch-and-exit()
  command-line-1(("-l" "test.el" "-f" "ert-run-tests-batch-and-exit"))
  command-line()
  normal-top-level()
Test test-filter=t condition:
    (void-function t)
   FAILED  1/1  test-filter=t (0.001650 sec)

Ran 1 tests, 0 results as expected, 1 unexpected (2021-10-16 18:21:53+0200, 0.115393 sec)

1 unexpected results:
   FAILED  test-filter=t


Helmut







^ permalink raw reply	[flat|nested] 23+ messages in thread

* bug#51177: 29.0.50; stop-process on pipes
  2021-10-16 16:24           ` Helmut Eller
@ 2021-10-16 16:47             ` Eli Zaretskii
  2021-10-16 17:07               ` Helmut Eller
  0 siblings, 1 reply; 23+ messages in thread
From: Eli Zaretskii @ 2021-10-16 16:47 UTC (permalink / raw)
  To: Helmut Eller; +Cc: larsi, 51177, jakanakaevangeli

> From: Helmut Eller <eller.helmut@gmail.com>
> Date: Sat, 16 Oct 2021 18:24:02 +0200
> Cc: 51177@debbugs.gnu.org, jakanakaevangeli@chiru.no
> 
> On Thu, Oct 14 2021, Lars Ingebrigtsen wrote:
> 
> > Helmut Eller <eller.helmut@gmail.com> writes:
> >
> >> I did not read the docstring but I did read the manual.  This feature is
> >> not described in the manual.  At least not near set-process-filter.
> >
> > Yup.  I've now documented the t value in the manual in emacs-28.
> 
> The t value also doesn't seem be handled correctly by make-process:
> 
> (ert-deftest test-filter=t ()
>   (let ((p (make-process :command '("dd" "if=/dev/zero" "count=0")
> 			 :name "foo"
> 			 :filter t)))
>     ;;(set-process-filter p t)
>     (while (eq (process-status p) 'run)
>       (accept-process-output p))))
> 
> when executed with
> 
>   emacs -Q --batch -l test.el -f ert-run-tests-batch-and-exit
> 
> produces:
> 
> Running 1 tests (2021-10-16 18:21:53+0200, selector ‘t’)
> Test test-filter=t backtrace:
>   t(#<process foo> "0+0 records in\n0+0 records out\n")
>   accept-process-output(#<process foo>)

What do we expect to happen when a Lisp program calls
accept-process-output on a process that is stopped?





^ permalink raw reply	[flat|nested] 23+ messages in thread

* bug#51177: 29.0.50; stop-process on pipes
  2021-10-16 16:47             ` Eli Zaretskii
@ 2021-10-16 17:07               ` Helmut Eller
  2021-10-18  6:58                 ` Lars Ingebrigtsen
  0 siblings, 1 reply; 23+ messages in thread
From: Helmut Eller @ 2021-10-16 17:07 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: larsi, 51177, jakanakaevangeli

On Sat, Oct 16 2021, Eli Zaretskii wrote:
>> Running 1 tests (2021-10-16 18:21:53+0200, selector ‘t’)
>> Test test-filter=t backtrace:
>>   t(#<process foo> "0+0 records in\n0+0 records out\n")
>>   accept-process-output(#<process foo>)
>
> What do we expect to happen when a Lisp program calls
> accept-process-output on a process that is stopped?

I would not expect that the symbol t will be called.

I would expect that accept-process-output on a process initialized with

   (make-process ... :filter t)

and

   (set-process-filter (make-process ...) t)

does the same.

I would expect that accept-process-output checks and maybe updates the
process-status.  If the process-status hasn't changed, then the return
value of accept-process-output should be nil.

Helmut





^ permalink raw reply	[flat|nested] 23+ messages in thread

* bug#51177: 29.0.50; stop-process on pipes
  2021-10-16 17:07               ` Helmut Eller
@ 2021-10-18  6:58                 ` Lars Ingebrigtsen
  0 siblings, 0 replies; 23+ messages in thread
From: Lars Ingebrigtsen @ 2021-10-18  6:58 UTC (permalink / raw)
  To: Helmut Eller; +Cc: 51177, jakanakaevangeli

Helmut Eller <eller.helmut@gmail.com> writes:

> I would expect that accept-process-output on a process initialized with
>
>    (make-process ... :filter t)
>
> and
>
>    (set-process-filter (make-process ...) t)
>
> does the same.

Yes, I think that makes sense.  And there was some support for it
already, but not in all the code paths.  I've adjusted this in Emacs 29
now.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





^ permalink raw reply	[flat|nested] 23+ messages in thread

* bug#51177: 29.0.50; stop-process on pipes
  2021-10-13  9:20 bug#51177: 29.0.50; stop-process on pipes Helmut Eller
  2021-10-13 11:45 ` Lars Ingebrigtsen
  2021-10-13 13:01 ` Eli Zaretskii
@ 2021-11-11 19:47 ` Helmut Eller
  2021-11-12  3:35   ` Lars Ingebrigtsen
  2 siblings, 1 reply; 23+ messages in thread
From: Helmut Eller @ 2021-11-11 19:47 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: 51177

I have another problem with stopped output.  In this example:

;;; -*- lexical-binding:t -*-

(ert-deftest test-read-after-exit ()
  (let* ((output "")
	 (filter (lambda (p s) (setq output (concat output s))))
	 (sentinel (lambda (p _)
		     (set-process-filter p filter)
		     (while (accept-process-output p 0))))
	 (proc (make-process :command '("printf" "foo")
			     :name "test-proc"
			     :filter t
			     :sentinel sentinel
			     :connection-type 'pipe)))
    (while (process-live-p proc)
      (accept-process-output proc 0.2))
    (set-process-filter proc filter)
    (while (accept-process-output proc 0))
    (should (equal output "foo"))))

the filter function is never called.

We could say that reading the process's output after the process has
terminated is an unreasonable request.  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.

Helmut





^ permalink raw reply	[flat|nested] 23+ messages in thread

* bug#51177: 29.0.50; stop-process on pipes
  2021-11-11 19:47 ` Helmut Eller
@ 2021-11-12  3:35   ` Lars Ingebrigtsen
  2021-11-12  5:13     ` Helmut Eller
  0 siblings, 1 reply; 23+ messages in thread
From: Lars Ingebrigtsen @ 2021-11-12  3:35 UTC (permalink / raw)
  To: Helmut Eller; +Cc: 51177

Helmut Eller <eller.helmut@gmail.com> writes:

> We could say that reading the process's output after the process has
> terminated is an unreasonable request.

I'm not sure I quite understand -- all the output from the process
should be delivered (to the filter function) before Emacs marks the
process as terminated, I think?

> 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...

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





^ permalink raw reply	[flat|nested] 23+ messages in thread

* bug#51177: 29.0.50; stop-process on pipes
  2021-11-12  3:35   ` Lars Ingebrigtsen
@ 2021-11-12  5:13     ` Helmut Eller
  2021-11-12  6:30       ` Lars Ingebrigtsen
  0 siblings, 1 reply; 23+ messages in thread
From: Helmut Eller @ 2021-11-12  5:13 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: 51177

[-- Attachment #1: Type: text/plain, Size: 1081 bytes --]

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.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: sentinel.patch --]
[-- Type: text/x-diff, Size: 1377 bytes --]

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 */
 

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* bug#51177: 29.0.50; stop-process on pipes
  2021-11-12  5:13     ` Helmut Eller
@ 2021-11-12  6:30       ` Lars Ingebrigtsen
  2021-11-12  7:21         ` Eli Zaretskii
  0 siblings, 1 reply; 23+ messages in thread
From: Lars Ingebrigtsen @ 2021-11-12  6:30 UTC (permalink / raw)
  To: Helmut Eller; +Cc: 51177

Helmut Eller <eller.helmut@gmail.com> writes:

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

Ah, I see.  No, that's not very intuitive.  😀

As for the patch itself, I'd worry that a subtle change in semantics
here would break stuff (and this is an area that's full of notoriously
subtle things), but perhaps it's OK.  Anybody have an opinion here?

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





^ permalink raw reply	[flat|nested] 23+ messages in thread

* bug#51177: 29.0.50; stop-process on pipes
  2021-11-12  6:30       ` Lars Ingebrigtsen
@ 2021-11-12  7:21         ` Eli Zaretskii
  2021-11-12  8:28           ` Helmut Eller
  0 siblings, 1 reply; 23+ messages in thread
From: Eli Zaretskii @ 2021-11-12  7:21 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: 51177, eller.helmut

> From: Lars Ingebrigtsen <larsi@gnus.org>
> Date: Fri, 12 Nov 2021 07:30:45 +0100
> Cc: 51177@debbugs.gnu.org
> 
> As for the patch itself, I'd worry that a subtle change in semantics
> here would break stuff (and this is an area that's full of notoriously
> subtle things), but perhaps it's OK.  Anybody have an opinion here?

First, the patch included an fprintf that should probably be removed.

And second, I'd prefer to have a variable exposed to Lisp to control
this behavior, so that if someone finds some strange consequences, we
could ask them to flip the variable and see if the problem goes away.

My main worry is what happens if we try reading from a pipe to a
process that died, and so its end of the pipe could be closed.  Was
this patch tested when process-connection-type is nil?





^ permalink raw reply	[flat|nested] 23+ messages in thread

* bug#51177: 29.0.50; stop-process on pipes
  2021-11-12  7:21         ` Eli Zaretskii
@ 2021-11-12  8:28           ` Helmut Eller
  2021-11-12 12:00             ` Eli Zaretskii
  2021-11-12 12:58             ` Helmut Eller
  0 siblings, 2 replies; 23+ messages in thread
From: Helmut Eller @ 2021-11-12  8:28 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Lars Ingebrigtsen, 51177

On Fri, Nov 12 2021, Eli Zaretskii wrote:

>> From: Lars Ingebrigtsen <larsi@gnus.org>
>> Date: Fri, 12 Nov 2021 07:30:45 +0100
>> Cc: 51177@debbugs.gnu.org
>> 
>> As for the patch itself, I'd worry that a subtle change in semantics
>> here would break stuff (and this is an area that's full of notoriously
>> subtle things), but perhaps it's OK.  Anybody have an opinion here?

Ideally, there'd be test suite for those subtleties...

> First, the patch included an fprintf that should probably be removed.

Yes, of course.

> And second, I'd prefer to have a variable exposed to Lisp to control
> this behavior, so that if someone finds some strange consequences, we
> could ask them to flip the variable and see if the problem goes away.

Maybe that variable could be the filter itself.  We could delay closing
file descriptors only if the filter==t.  For the other values,
everything could stay as now.

> My main worry is what happens if we try reading from a pipe to a
> process that died, and so its end of the pipe could be closed.  Was
> this patch tested when process-connection-type is nil?

Just tested it.  Works.

I do wonder why the part of the code with the comment "If process is
still active, read any output that remains" is not executed for the
deleting_process.  It seems to me that this creates the possibility (with
very low probability) that we forget to read the last chunk of output in
the usual case where filter ≠ t.

Helmut





^ permalink raw reply	[flat|nested] 23+ messages in thread

* bug#51177: 29.0.50; stop-process on pipes
  2021-11-12  8:28           ` Helmut Eller
@ 2021-11-12 12:00             ` Eli Zaretskii
  2021-11-12 12:34               ` Helmut Eller
  2021-11-12 12:58             ` Helmut Eller
  1 sibling, 1 reply; 23+ messages in thread
From: Eli Zaretskii @ 2021-11-12 12:00 UTC (permalink / raw)
  To: Helmut Eller; +Cc: larsi, 51177

> From: Helmut Eller <eller.helmut@gmail.com>
> Cc: Lars Ingebrigtsen <larsi@gnus.org>,  51177@debbugs.gnu.org
> Date: Fri, 12 Nov 2021 09:28:49 +0100
> 
> > My main worry is what happens if we try reading from a pipe to a
> > process that died, and so its end of the pipe could be closed.  Was
> > this patch tested when process-connection-type is nil?
> 
> Just tested it.  Works.

On what OS?





^ permalink raw reply	[flat|nested] 23+ messages in thread

* bug#51177: 29.0.50; stop-process on pipes
  2021-11-12 12:00             ` Eli Zaretskii
@ 2021-11-12 12:34               ` Helmut Eller
  2021-11-12 13:05                 ` Eli Zaretskii
  0 siblings, 1 reply; 23+ messages in thread
From: Helmut Eller @ 2021-11-12 12:34 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: larsi, 51177

On Fri, Nov 12 2021, Eli Zaretskii wrote:

>> > My main worry is what happens if we try reading from a pipe to a
>> > process that died, and so its end of the pipe could be closed.  Was
>> > this patch tested when process-connection-type is nil?
>> 
>> Just tested it.  Works.
>
> On what OS?

On GNU/Linux.





^ permalink raw reply	[flat|nested] 23+ messages in thread

* bug#51177: 29.0.50; stop-process on pipes
  2021-11-12  8:28           ` Helmut Eller
  2021-11-12 12:00             ` Eli Zaretskii
@ 2021-11-12 12:58             ` Helmut Eller
  1 sibling, 0 replies; 23+ messages in thread
From: Helmut Eller @ 2021-11-12 12:58 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Lars Ingebrigtsen, 51177

On Fri, Nov 12 2021, Helmut Eller wrote:

> I do wonder why the part of the code with the comment "If process is
> still active, read any output that remains" is not executed for the
> deleting_process.  It seems to me that this creates the possibility (with
> very low probability) that we forget to read the last chunk of output in
> the usual case where filter ≠ t.

I see now why.  The Fdelete_process uses (p->infd >= 0) to decide if it
should call status_notify.  I guess this is pretty much a show stopper
as this will result in an endless recursion when delete-process is
called from a sentinel without closing the file descriptors first.

Helmut





^ permalink raw reply	[flat|nested] 23+ messages in thread

* bug#51177: 29.0.50; stop-process on pipes
  2021-11-12 12:34               ` Helmut Eller
@ 2021-11-12 13:05                 ` Eli Zaretskii
  2021-11-12 13:26                   ` Helmut Eller
  0 siblings, 1 reply; 23+ messages in thread
From: Eli Zaretskii @ 2021-11-12 13:05 UTC (permalink / raw)
  To: Helmut Eller; +Cc: larsi, 51177

> From: Helmut Eller <eller.helmut@gmail.com>
> Cc: larsi@gnus.org,  51177@debbugs.gnu.org
> Date: Fri, 12 Nov 2021 13:34:24 +0100
> 
> On Fri, Nov 12 2021, Eli Zaretskii wrote:
> 
> >> > My main worry is what happens if we try reading from a pipe to a
> >> > process that died, and so its end of the pipe could be closed.  Was
> >> > this patch tested when process-connection-type is nil?
> >> 
> >> Just tested it.  Works.
> >
> > On what OS?
> 
> On GNU/Linux.

Thanks.  Can you show a recipe for testing this?





^ permalink raw reply	[flat|nested] 23+ messages in thread

* bug#51177: 29.0.50; stop-process on pipes
  2021-11-12 13:05                 ` Eli Zaretskii
@ 2021-11-12 13:26                   ` Helmut Eller
  0 siblings, 0 replies; 23+ messages in thread
From: Helmut Eller @ 2021-11-12 13:26 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: larsi, 51177

On Fri, Nov 12 2021, Eli Zaretskii wrote:

> Thanks.  Can you show a recipe for testing this?

Create a file with this code:

(ert-deftest test-read-after-exit ()
  (let* ((output "")
	 (filter (lambda (p s) (setq output (concat output s))))
	 (sentinel (lambda (p _)
		     (set-process-filter p filter)
		     (while (accept-process-output p 0))))
	 (proc (make-process :command '("printf" "foo")
			     :name "test-proc"
			     :filter t
			     :sentinel sentinel)))
    (while (process-live-p proc)
      (accept-process-output proc 0.2))
    (should (equal output "foo"))))

and execute: emacs -Q --batch -l test.el -f ert-run-tests-batch-and-exit

However, if delete-process is called from the sentinel like so

(ert-deftest test-delete-proces ()
  (let* ((output "")
	 (filter (lambda (p s) (setq output (concat output s))))
	 (sentinel (lambda (p _)
		     (set-process-filter p filter)
		     (while (accept-process-output p 0))
		     (delete-process p)))
	 (proc (make-process :command '("printf" "foo")
			     :name "test-proc"
			     :filter t
			     :sentinel sentinel)))
    (while (process-live-p proc)
      (accept-process-output proc 0.2))
    (should (equal output "foo"))))


then it produces an endless loop.

Helmut





^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2021-11-12 13:26 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-13  9:20 bug#51177: 29.0.50; stop-process on pipes Helmut Eller
2021-10-13 11:45 ` Lars Ingebrigtsen
2021-10-13 13:39   ` Helmut Eller
2021-10-13 13:01 ` Eli Zaretskii
2021-10-13 14:04   ` Helmut Eller
2021-10-14  7:51     ` jakanakaevangeli
2021-10-14  8:00       ` Helmut Eller
2021-10-14 11:10         ` Lars Ingebrigtsen
2021-10-16 16:24           ` Helmut Eller
2021-10-16 16:47             ` Eli Zaretskii
2021-10-16 17:07               ` Helmut Eller
2021-10-18  6:58                 ` Lars Ingebrigtsen
2021-11-11 19:47 ` Helmut Eller
2021-11-12  3:35   ` Lars Ingebrigtsen
2021-11-12  5:13     ` Helmut Eller
2021-11-12  6:30       ` Lars Ingebrigtsen
2021-11-12  7:21         ` Eli Zaretskii
2021-11-12  8:28           ` Helmut Eller
2021-11-12 12:00             ` Eli Zaretskii
2021-11-12 12:34               ` Helmut Eller
2021-11-12 13:05                 ` Eli Zaretskii
2021-11-12 13:26                   ` Helmut Eller
2021-11-12 12:58             ` Helmut Eller

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).