help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: unwind-protect and inhibit-quit


From: Felix Dietrich
Subject: Re: unwind-protect and inhibit-quit
Date: Sat, 17 Jul 2021 17:46:52 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/27.1 (gnu/linux)

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Felix Dietrich <felix.dietrich@sperrhaken.name>
>> Date: Fri, 16 Jul 2021 23:30:31 +0200
>
>> The macro ‘with-local-quit’ states that the “quit-flag” “will not be
>> handled until the next function call”[1].  Could, therefore, a
>> careful and cooperative “ftp-setup-buffer” ensure that the process
>> is either cleaned-up or returned?
>
> There's no way to ensure atomicity on the Lisp level, because a Lisp
> program has no real control of when quit handling happens.  Only
> primitives can do that (and actually do that where we think it's
> necessary).
>
> What problem(s) this is intended to fix/handle?

Still the problem of process littering and, more generally, ensuring
that certain clean up operations are run and values needed for those
clean up operations are not lost in limbo.  I admit that this problem,
that quit is signalled so timed that the return value of a function is
lost in that ethereal space between return and assignment, is an so
unlikely one that one may ignore it in practice—but it piqued my
interest.

Take an ‘ftp-setup-buffer’ function like the following:


    (defun ftp-setup-buffer ()
      (let (process)
        (condition-case err
            (progn
              (setq process (start-process …))
               process ; RETURN
              )
          (quit
           (and (processp process)
                (kill-process process))
           (signal (car err) (cdr err))))))


If you can 1. trust that ‘start-process’ will either return a process
object or, in case of a quit, clean-up whatever intermediary process it
may have created before it propagates the quit, and 2.1. that a quit
received while a RETURN is in process is either signalled inside the
called ‘ftp-setup-buffer’ at a point where in can still be handled by
the ‘condition-case’ or 2.2. only once the returned value has either
been assigned or became irrelevant in the caller because the next form
is being evaluated, then canʼt killing of the process be guaranteed?

This leaves out the issue that another quit may occur inside a handler.
It would be nice if a handler could be started with ‘inhibit-quit’
non-nil.  Let me make something up:


    (condition-case err
        (do-stuff)
      ((:inhibit-quit quit)
       (clean-stuff-up)
       (signal (car err) (cdr err))))


The caller of ‘ftp-setup-buffer’ would not have to worry anymore that
the process object he requested might be lost in transit when a quit
occurs: either ‘ftp-setup-buffer’ has returned a process object, and it
was assigned to the ‘process’ variable, or the process object was killed
already in ‘ftp-setup-buffer’.  (Of course the ‘unwind-protect’ handler
suffers also from the issue that the user may send a quit while it is
being evaluated.)


    (let (process)
      (unwind-protect
          (setq process (ftp-setup-buffer …))
        (and (processp process)
             (kill-process process))))


Alas, it is probably not as “simple” as I imagine: what have I missed?
What do I not know?

-- 
Felix Dietrich



reply via email to

[Prev in Thread] Current Thread [Next in Thread]