unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* PROPOSAL: Control over process cleanup in `save-buffers-kill-emacs'.
@ 2017-09-22 18:58 Karl Fogel
  2017-09-22 19:11 ` Davis Herring
  2017-09-22 19:26 ` Eli Zaretskii
  0 siblings, 2 replies; 3+ messages in thread
From: Karl Fogel @ 2017-09-22 18:58 UTC (permalink / raw)
  To: Emacs Development

In `save-buffers-kill-emacs' in files.el, we check for active processes -- the familiar "Active processes exist; kill them and exit anyway? " query -- and then only at the very end of the function do we run `kill-emacs-query-functions' and call `kill-emacs' (which then runs the hooks in `kill-emacs-hook' of course).

This means that neither `kill-emacs-query-functions' nor `kill-emacs-hook' happen in time to offer any fine-grained control over whether the user gets queried about active processes.  And since the `confirm-kill-processes' flag applies to all processes, one can't use it to customize *which* processes one is queried about at exit time.

I propose moving `kill-emacs-query-functions' to before the process-killing block, so that hooks can do things with processes before Emacs asks about those processes.  I haven't tested this patch yet, but this gives the idea:

  --- lisp/files.el
  +++ lisp/files.el
  @@ -6875,6 +6875,7 @@ save-buffers-kill-emacs
                                 (buffer-list))))
            (progn (setq confirm nil)
                   (yes-or-no-p "Modified buffers exist; exit anyway? ")))
  +     (run-hook-with-args-until-failure 'kill-emacs-query-functions)
        (or (not (fboundp 'process-list))
            ;; process-list is not defined on MSDOS.
            (not confirm-kill-processes)
  @@ -6897,8 +6898,6 @@ save-buffers-kill-emacs
                           (when (window-live-p window)
                             (quit-restore-window window 'kill)))))
                   (list-processes t)))))
  -     ;; Query the user for other things, perhaps.
  -     (run-hook-with-args-until-failure 'kill-emacs-query-functions)
        (or (null confirm)
            (funcall confirm "Really exit Emacs? "))
        (kill-emacs))))

Justification:

Sometimes there are expected processes that one knows it's okay to kill at exit time, but one would prefer to be queried about any unexpected processes (perhaps there is a long-running job that one forgot about, and one would answer "no" to exiting Emacs if one were reminded about that job).

For example, I just started using IMAP (instead of local spool source) to fetch email into Gnus.  Since I'm querying two separate IMAP servers, there are two separate IMAP buffers each with its own process.  When I exit Emacs, I do not need to be queried about those process buffers -- I know it's okay for Emacs to kill the processes.  But I can't easily do `set-process-query-on-exit-flag' at the time the IMAP processes are started, since I just run `M-x gnus' and then somewhen after that something runs IMAP (maybe there's a hook for this somewhere, but if so, I haven't found it yet).

But I could put code like this into a hook, if only there were a hook that were run before the process-killing block in `save-buffers-kill-emacs':

  (mapcar (lambda (buf)
            (when (string-match "^ \\*imap source\\*.*" (buffer-name buf))
              (message "shutting down IMAP process '%s'" (get-buffer-process buf)) 
              (set-process-query-on-exit-flag (get-buffer-process buf) nil)
              (kill-buffer buf)))
          (buffer-list))

I think it would be generally useful to offer the ability to have custom process cleanup at exit time.

My only reservation about the change is that the hook name `kill-emacs-query-functions' perhaps becomes even less accurate (though it is already potentially inaccurate, depending on how people are using it).  In fact, my personal use would be in order to *avoid* some queries, not to perform any new queries.  But for all I know, people are already using that hook to do things that have nothing to do with queries, so maybe moving it earlier doesn't add to the problem.

(A further possibility is to put the hook call at the very beginning of the function, even before the big `let', so that the hooks is run even before the "Modified buffers exist; exit anyway? " check.  I'm not sure whether that would be useful or not; since I don't have a concrete use case for it, I'm not pushing for it here.)

For reference, here's the entire function as it stands right now, current tip (commit 908af46abdb) of the "emacs-26" branch:

(defun save-buffers-kill-emacs (&optional arg)
  "Offer to save each buffer, then kill this Emacs process.
With prefix ARG, silently save all file-visiting buffers without asking.
If there are active processes where `process-query-on-exit-flag'
returns non-nil and `confirm-kill-processes' is non-nil,
asks whether processes should be killed.
Runs the members of `kill-emacs-query-functions' in turn and stops
if any returns nil.  If `confirm-kill-emacs' is non-nil, calls it."
  (interactive "P")
  ;; Don't use save-some-buffers-default-predicate, because we want
  ;; to ask about all the buffers before killing Emacs.
  (save-some-buffers arg t)
  (let ((confirm confirm-kill-emacs))
    (and
     (or (not (memq t (mapcar (function
                               (lambda (buf) (and (buffer-file-name buf)
                                                  (buffer-modified-p buf))))
                              (buffer-list))))
         (progn (setq confirm nil)
                (yes-or-no-p "Modified buffers exist; exit anyway? ")))
     (or (not (fboundp 'process-list))
         ;; process-list is not defined on MSDOS.
         (not confirm-kill-processes)
         (let ((processes (process-list))
               active)
           (while processes
             (and (memq (process-status (car processes)) '(run stop open listen))
                  (process-query-on-exit-flag (car processes))
                  (setq active t))
             (setq processes (cdr processes)))
           (or (not active)
               (with-current-buffer-window
                (get-buffer-create "*Process List*") nil
                #'(lambda (window _value)
                    (with-selected-window window
                      (unwind-protect
                          (progn
                            (setq confirm nil)
                            (yes-or-no-p "Active processes exist; kill them and exit anyway? "))
                        (when (window-live-p window)
                          (quit-restore-window window 'kill)))))
                (list-processes t)))))
     ;; Query the user for other things, perhaps.
     (run-hook-with-args-until-failure 'kill-emacs-query-functions)
     (or (null confirm)
         (funcall confirm "Really exit Emacs? "))
     (kill-emacs))))

Thoughts,
-Karl



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

* Re: PROPOSAL: Control over process cleanup in `save-buffers-kill-emacs'.
  2017-09-22 18:58 PROPOSAL: Control over process cleanup in `save-buffers-kill-emacs' Karl Fogel
@ 2017-09-22 19:11 ` Davis Herring
  2017-09-22 19:26 ` Eli Zaretskii
  1 sibling, 0 replies; 3+ messages in thread
From: Davis Herring @ 2017-09-22 19:11 UTC (permalink / raw)
  To: Karl Fogel, Emacs Development

> This means that neither `kill-emacs-query-functions' nor `kill-emacs-hook' happen in time to offer any fine-grained control over whether the user gets queried about active processes.  And since the `confirm-kill-processes' flag applies to all processes, one can't use it to customize *which* processes one is queried about at exit time.
> 
> I propose moving `kill-emacs-query-functions' to before the process-killing block, so that hooks can do things with processes before Emacs asks about those processes.

Given your use case, it seems a lot less hackish to just introduce a 
user option that is one of

1. an abnormal hook called with each new process started

This would allow the use of `set-process-query-on-exit-flag' in a 
natural way, but would run before any existing code configured the 
process in similar fashion.

2. a new normal hook called at the beginning of `save-buffers-kill-emacs'

This would also allow the existing flag to be used, and would be 
unsurprising and easy to find.

3. a regular expression matching process and/or process-buffer names for 
which not to query on exit

This would allow access by non-programmers, but would make the query 
flag something of a lie.

Davis

-- 
This product is sold by volume, not by mass.  If it appears too dense or 
too sparse, it is because mass-energy conversion has occurred during 
shipping.



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

* Re: PROPOSAL: Control over process cleanup in `save-buffers-kill-emacs'.
  2017-09-22 18:58 PROPOSAL: Control over process cleanup in `save-buffers-kill-emacs' Karl Fogel
  2017-09-22 19:11 ` Davis Herring
@ 2017-09-22 19:26 ` Eli Zaretskii
  1 sibling, 0 replies; 3+ messages in thread
From: Eli Zaretskii @ 2017-09-22 19:26 UTC (permalink / raw)
  To: Karl Fogel; +Cc: emacs-devel

> From: Karl Fogel <kfogel@red-bean.com>
> Date: Fri, 22 Sep 2017 13:58:41 -0500
> 
> I propose moving `kill-emacs-query-functions' to before the process-killing block, so that hooks can do things with processes before Emacs asks about those processes.  I haven't tested this patch yet, but this gives the idea:

We have process-query-on-exit-flag for that.

> But I can't easily do `set-process-query-on-exit-flag' at the time the IMAP processes are started, since I just run `M-x gnus' and then somewhen after that something runs IMAP (maybe there's a hook for this somewhere, but if so, I haven't found it yet).

Then perhaps we need a facility to set this flag on certain classes of
processes?

> But I could put code like this into a hook, if only there were a hook that were run before the process-killing block in `save-buffers-kill-emacs':
> 
>   (mapcar (lambda (buf)
>             (when (string-match "^ \\*imap source\\*.*" (buffer-name buf))
>               (message "shutting down IMAP process '%s'" (get-buffer-process buf)) 
>               (set-process-query-on-exit-flag (get-buffer-process buf) nil)
>               (kill-buffer buf)))
>           (buffer-list))

Why cannot you do something similar in the process sentinel, which is
called when the process begins?  Or maybe Gnus should provide a
facility to set this flag for the processes it starts?

In any case, if this is somehow impossible today, I think we should
extend the facilities that allow setting this flag, instead of
inventing a separate parallel mechanism.

Thanks.



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

end of thread, other threads:[~2017-09-22 19:26 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-22 18:58 PROPOSAL: Control over process cleanup in `save-buffers-kill-emacs' Karl Fogel
2017-09-22 19:11 ` Davis Herring
2017-09-22 19:26 ` Eli Zaretskii

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