From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Jim Porter Newsgroups: gmane.emacs.bugs 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 Message-ID: <79a53ecc-dbfc-d088-d80d-96f349be794a@gmail.com> References: <9e47c871-a2c3-d764-bec9-d87abf3efe83@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="11192"; mail-complaints-to="usenet@ciao.gmane.io" Cc: larsi@gnus.org, gregory@heytings.org To: 51993@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Mon Nov 29 06:40:14 2021 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1mrZOg-0002lY-7Z for geb-bug-gnu-emacs@m.gmane-mx.org; Mon, 29 Nov 2021 06:40:14 +0100 Original-Received: from localhost ([::1]:56296 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mrZOe-0006Sy-CC for geb-bug-gnu-emacs@m.gmane-mx.org; Mon, 29 Nov 2021 00:40:12 -0500 Original-Received: from eggs.gnu.org ([209.51.188.92]:44768) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mrZOU-0006Sp-NF for bug-gnu-emacs@gnu.org; Mon, 29 Nov 2021 00:40:02 -0500 Original-Received: from debbugs.gnu.org ([209.51.188.43]:53434) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1mrZOU-0001de-Ek for bug-gnu-emacs@gnu.org; Mon, 29 Nov 2021 00:40:02 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1mrZOU-0002Jw-7R for bug-gnu-emacs@gnu.org; Mon, 29 Nov 2021 00:40:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Jim Porter Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Mon, 29 Nov 2021 05:40:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 51993 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 51993-submit@debbugs.gnu.org id=B51993.16381643958904 (code B ref 51993); Mon, 29 Nov 2021 05:40:02 +0000 Original-Received: (at 51993) by debbugs.gnu.org; 29 Nov 2021 05:39:55 +0000 Original-Received: from localhost ([127.0.0.1]:36747 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mrZON-0002JX-7O for submit@debbugs.gnu.org; Mon, 29 Nov 2021 00:39:55 -0500 Original-Received: from mail-pj1-f45.google.com ([209.85.216.45]:34369) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mrZOK-0002JJ-VF for 51993@debbugs.gnu.org; Mon, 29 Nov 2021 00:39:53 -0500 Original-Received: by mail-pj1-f45.google.com with SMTP id j5-20020a17090a318500b001a6c749e697so11041060pjb.1 for <51993@debbugs.gnu.org>; Sun, 28 Nov 2021 21:39:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=subject:from:to:references:cc:message-id:date:mime-version :in-reply-to:content-language:content-transfer-encoding; bh=TcOD8gV4/1F8u3Gq3ZX7Z1KPjVlcHDIyh2ZALQwH8OY=; b=Z5mx6e1k5f14ncuMTuv1h7ovNtP/7IYS9BT798q9xZozpMgUp+woWhQivYqXIH4fba 1MxZ5bfnyaTl7KhL8XEO6ugkoYHOpfIndbDxDcXyFowZDXupeJUU4v4zkQFIAwTvTBwf oLTB4ddZs3AkKe14BPBphm0RjgLlA4XbNcMdIyKRmSKIO3XrKd47geQS4vCQaZ2EqmO6 dMATRzXQuHPycPJDM2Kt+6F42hlhzJwiV0scRfsXRkjFtVPWmxjsLZJzX4ihFLHPsJtK pmELJ4cfgA52x83ofurHS+y+iGhANzyUp2SigS0WWNDrX1fLXVB3wPfT/RW9EiutY/fj D0Ew== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:subject:from:to:references:cc:message-id:date :mime-version:in-reply-to:content-language:content-transfer-encoding; bh=TcOD8gV4/1F8u3Gq3ZX7Z1KPjVlcHDIyh2ZALQwH8OY=; b=7GDTn8pmAPAZa1LfttJLfID6XVHuU9XRkaCFNY/rxMgvo8xEZEtpwriZs7W3OLZbh/ dIvzOLoav+bpW+n/FiS+y5SHwKCkcN0tDNJc08nLN38LjBj9AA+tbn6bp0WAL9ftbBVc n7sxI6Fj8cvH/XkFzQrPUNADBjbZ0iWAgl7UdvbRPrr+SvJIoVW0Jzqc7wk3GfZLhxtN v953I9GkW2h7bzfwYdKisQ0uz/7K7YmyslsRT3WShR9JBboWr8lZdeoPzDoSprTU0A9Q 6z91WbRUm+hrkrWe3JcM3reqxMJT8AW7qwSYT2aku1ycG179XsPUVl3EVZ9vDo/mSPTZ hquA== X-Gm-Message-State: AOAM533nzRX0G0IRaIedAthFPug/beeTIjP9lDtSS5XRFO2SZd6CfeIP pLzsJ+EHbGERrLWYy1XfoPD1Leufa0E= X-Google-Smtp-Source: ABdhPJw0EZ1YBRrnhIg1DGfkP6LRndjmj60XCivxZVNsrP/4pQ4LJCP9t1OHA8/fuxtzIzsCxqjfJg== X-Received: by 2002:a17:90a:e012:: with SMTP id u18mr36206450pjy.103.1638164386992; Sun, 28 Nov 2021 21:39:46 -0800 (PST) Original-Received: from [192.168.1.2] (cpe-76-168-148-233.socal.res.rr.com. [76.168.148.233]) by smtp.googlemail.com with ESMTPSA id 7sm11224503pgk.55.2021.11.28.21.39.45 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 28 Nov 2021 21:39:46 -0800 (PST) In-Reply-To: <9e47c871-a2c3-d764-bec9-d87abf3efe83@gmail.com> Content-Language: en-US X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.io gmane.emacs.bugs:220985 Archived-At: 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.