From: Jim Porter <jporterbugs@gmail.com>
To: 51993@debbugs.gnu.org
Cc: larsi@gnus.org, gregory@heytings.org
Subject: bug#51993: 29.0.50; [PATCH] Killing emacsclient terminal with `server-stop-automatically' doesn't prompt to save files
Date: Sun, 28 Nov 2021 21:39:46 -0800 [thread overview]
Message-ID: <79a53ecc-dbfc-d088-d80d-96f349be794a@gmail.com> (raw)
In-Reply-To: <9e47c871-a2c3-d764-bec9-d87abf3efe83@gmail.com>
To help move things along, I've drafted an initial version of a proposal
describing possible behaviors of `server-stop-automatically' at a high
level. Hopefully that will make it easier to discuss how each setting
should work, and we can refine the proposal until we're happy with it.
Then any implementation changes should "just" be a matter of following
the final proposal.
I welcome any comments or suggested additions to this proposal. I
covered things how I see them, but I may not have provided enough detail
for everyone to understand all the nuances, and other people might have
their own use cases they'd like to see addressed.
I can also post this proposal to emacs-devel if people think it would be
better to get a wider range of feedback on it. Once we can get some
level of consensus on the proposal, then hopefully we'll know the right
thing to do about this bug.
--------------------
Automatically Shutting Down the Emacs Daemon
Revision 1
* Introduction
Since Emacs 23, `emacsclient' has had the ability to automatically start
an Emacs daemon by passing `--alternate-editor=""' (or setting the
ALTERNATE_EDITOR environment variable to the empty string). In Emacs 29,
the ability to automatically shut down the daemon was added for
symmetry. This allows users who prefer to start the Emacs daemon on an
as-needed basis to configure the daemon to stop when finished. However,
"finished" is a vague term and doesn't precisely describe the conditions
that would cause the Emacs daemon to be shut down.
Note: for the discussion below, "clients" refers to both "true clients"
(members of `server-clients') and "pseudo-clients" (each frame with the
`client' parameter set to `nowait'). This is essentially the logic used
by `server-save-buffers-kill-terminal' since Emacs 23.
* Proposed Behaviors
I propose two main ways of determining when the Emacs daemon should be
shut down automatically. Each has different pros and cons, and so there
are arguments for supporting one, both, or neither in Emacs going
forward. However, I think each are distinct enough that supporting both
would be reasonable.
** Implicit Shutdown
For this behavior, the Emacs daemon will be silently stopped once
nothing would be lost by stopping it. In particular, this means that the
Emacs daemon should continue so long as there's at least one a) active
client, b) unsaved file, or c) running subprocess (with non-nil
`process-query-on-exit-flag'). If none of these exist, then the Emacs
daemon will be stopped.
One open question is how this should interact with options that control
how `save-buffers-kill-emacs' prompts the user. If
`confirm-kill-processes' is nil, should the Emacs daemon then be stopped
even if there are active subprocesses?
*** Pros
A benefit of this behavior is that because the shutdown occurs
implicitly, there's no change to how users interact with Emacs. For
example, `save-buffers-kill-terminal' will prompt the user to save only
those files passed to `emacsclient'.
*** Cons
However, the behavior's benefit has another side to it: it can be
difficult for a user to predict whether the Emacs daemon will be
stopped. For example, a stray unsaved file that the user forgot about
could be the difference between the daemon continuing to run or being
stopped.
Furthermore, since an Emacs daemon with no clients is out of sight, it
may be some time before the user realizes their mistake, leading to
confusion about why some other program appears to be reading an
out-of-date version of the file. That said, this aspect is equally a
concern when *not* automatically stopping the Emacs daemon at all.
** Explicit Shutdown
(Note: this is the behavior I personally prefer.) In this case, Emacs
will be stopped as soon as there are no active clients, prompting the
user to save their work as needed. In other words, when a client is
about to be deleted for any reason (calling
`server-save-buffers-kill-terminal', deleting the last frame associated
with the client, etc), then:
- If this is not the last client, behave as in Emacs 28; that is, prompt
to save any files passed to `emacsclient' before deleting the client.
- If this is the last client, prompt the user to save all their work
before killing Emacs entirely; that is, call `save-buffers-kill-emacs'.
In this case, the behavior should be identical (or as close as possible)
to killing a "regular", non-server Emacs in a similar state.
One open question is: should Emacs warn the user that it will the daemon
when deleting the last client? Currently it does so in
`server-kill-emacs-query-function', asking, "This Emacs session has
clients; exit anyway?" It may be useful to keep this warning, possibly
rewording it in this case to explain the situation better. It's also
possible that it's just extra noise and should be eliminate in this
case. (It may even make sense to provide a separate configuration option.)
*** Pros
One of the main goals with Explicit Shutdown is to resolve a concern
mentioned above: an Emacs daemon with no clients is out of sight, so
it's easy to forget about it. If the daemon is holding onto unsaved
work, it may take a while until the user realizes this. By prompting to
save *all* the user's work before closing the last client, it's much
harder to make this mistake.
*** Cons
This behavior makes it more difficult for a user to know ahead of time
whether `save-buffers-kill-terminal' (bound by default to `C-x C-c')
will kill the client or Emacs entirely. The prompt mentioned above in
`server-kill-emacs-query-function' does let the user bail out though, if
they didn't mean to kill Emacs entirely.
However, `save-buffers-kill-terminal' already has this complexity
(almost), since it will kill Emacs entirely when executed from a
non-client frame. That said, it's possible to tell what will happen in
this case by looking at the mode line: if it starts with something like
"U:@---", it's a client frame and thus an observant user will know what
`save-buffers-kill-terminal' will do.
* Delayed Shutdown
It may also be worth considering whether the Emacs daemon should be
stopped immediately when the conditions are met, or whether it would be
better to delay it by a short time. Some operations, such as `git rebase
-i', can open the $EDITOR, close it, and then reopen it in rapid
succession. In a case like that, it would be more efficient if the Emacs
daemon weren't stopped right away.
That said, I don't think this is a critical problem, and believe it
would be ok to decide what to do about this later.
* Current Behaviors
Currently, Emacs 29 supports Implicit Shutdown (called `empty') and has
two slightly-different variations on Explicit Shutdown (called
`kill-terminal' and `delete-frame'). `empty' is implemented as a timer
that periodically calls `server-stop-automatically--maybe-kill-emacs' to
check if there's any need to keep the daemon running (non-daemon frames,
unsaved files, or running processes); if not, it stops the daemon. This
differs very slightly from the proposed spec above, since it checks for
frames, not active clients. Some clients (e.g. `emacsclient --eval FOO')
don't create any frames, so it may be useful to enhance the current
implementation of Implicit Shutdown to account for this.
`kill-terminal' is implemented in
`server-stop-automatically--handle-delete-frame' (called by
`server-save-buffers-kill-terminal'). It first deletes all frames
associated with the current client *except* the current one. Then, if
there are any non-daemon frames aside from the current one, it just
deletes that frame; if it's the last non-daemon frame, it calls
`save-buffers-kill-emacs'.
`delete-frame' works like `kill-terminal' above, but will also call
`save-buffers-kill-emacs' when closing the last non-daemon frame using
other means, such as clicking the "X" in the frame's title bar on a GUI
system.
As mentioned above, `kill-terminal' and `delete-frame' work similarly to
the Explicit Shutdown behavior, but there are some differences. For
example, when killing a non-last client, `kill-terminal' and
`delete-frame' don't prompt to save files passed to `emacsclient'. When
killing the last client, they delete all the non-current frames before
calling `save-buffers-kill-emacs', meaning that pressing `C-g' to cancel
when prompted will still result in all but one frame going away.
next prev parent reply other threads:[~2021-11-29 5:39 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-11-20 4:29 bug#51993: 29.0.50; [PATCH] Killing emacsclient terminal with `server-stop-automatically' doesn't prompt to save files Jim Porter
2021-11-20 7:13 ` Eli Zaretskii
2021-11-23 9:48 ` Gregory Heytings
2021-11-23 18:25 ` Jim Porter
2021-11-23 20:37 ` Gregory Heytings
2021-11-23 22:08 ` Jim Porter
2021-11-23 22:49 ` Gregory Heytings
2021-11-23 23:42 ` Jim Porter
2021-11-23 23:59 ` Gregory Heytings
2021-11-24 1:10 ` Jim Porter
2021-11-29 5:39 ` Jim Porter [this message]
2021-11-29 12:41 ` Eli Zaretskii
2021-11-29 13:40 ` Gregory Heytings
2021-11-29 19:31 ` Jim Porter
2022-01-01 0:11 ` Jim Porter
2022-09-09 17:55 ` Lars Ingebrigtsen
2022-09-09 18:04 ` Jim Porter
2022-10-09 22:09 ` Jim Porter
2022-10-10 6:04 ` Eli Zaretskii
2022-10-20 3:14 ` Jim Porter
2022-10-20 6:23 ` Eli Zaretskii
2022-10-21 5:51 ` Jim Porter
2022-10-21 6:38 ` Eli Zaretskii
2022-10-22 3:46 ` Jim Porter
2022-10-22 6:57 ` Eli Zaretskii
2022-10-25 3:10 ` Jim Porter
2022-10-30 22:32 ` Jim Porter
2022-11-29 5:31 ` Jim Porter
2022-12-01 17:29 ` Eli Zaretskii
2022-12-02 1:09 ` bug#51993: 29.0.50; [PATCH for 29.1] " Jim Porter
2022-12-02 14:10 ` Eli Zaretskii
2022-12-02 21:33 ` Jim Porter
2022-12-04 17:56 ` Eli Zaretskii
2022-12-04 22:26 ` Jim Porter
2022-12-06 22:20 ` Jim Porter
2022-12-02 1:42 ` bug#51993: 29.0.50; [PATCH explanation] " Jim Porter
2022-12-02 14:31 ` Eli Zaretskii
2021-11-29 19:12 ` bug#51993: 29.0.50; [PATCH] " Jim Porter
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=79a53ecc-dbfc-d088-d80d-96f349be794a@gmail.com \
--to=jporterbugs@gmail.com \
--cc=51993@debbugs.gnu.org \
--cc=gregory@heytings.org \
--cc=larsi@gnus.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).