4

problem

Lately I run GNU Emacs mostly as GUI on X/tty7 (which I'll call "the desktop" as opposed to emacs-desktop) on one of my Debian laptops. Occasionally the desktop hangs, in which case I usually can goto tty1 and sudo shutdown -[whatever] now. Unfortunately this does not cause Emacs to shut down as cleanly as I'd like: I'd like Emacs to (e.g.) save any unsaved buffers and desktop-save, but that doesn't seem to get done.

So I'm thinking that, in this usecase, I should utter something from tty1 (before shutdown) to tell Emacs to shutdown cleanly ... but I don't know what to say. How to do this?

solution

thanks

TIA and for past help to the many fine folks @ help-gnu-emacs, esp Yuri Khan for the initial suggestion and Jorge A. Alfaro-Murillo for the more important details of this solution. Special thanks to Faried Nawaz for 2 important advances that pretty-much solve the problem.

server and client

One way that WFM (not entirely without problems--see notes below) is

  1. Preparation:

1.1. Whenever you start Emacs, make it start a server instance. I did this by adding the following line to my ~/.emacs.d/init.el:

    (server-start)

1.2. Also in ~/.emacs.d/init.el, define a callable function to tell emacs to shutdown cleanly, with as few prompts as possible. Faried Nawaz recommended

    (defun my-kill-emacs ()
      "Set kill-emacs-query-functions , confirm-kill-emacs , and
    kill-emacs-hook to nil to quit emacs without any pesky prompts
    (except to save buffers)"
      (let (kill-emacs-query-functions confirm-kill-emacs kill-emacs-hook)
        (save-buffers-kill-emacs)))

1.3. Restart your emacs to be sure to incorporate your new init.el code.

  1. When you encounter tty7/desktop hang: Goto tty1, and login if not already. Then do either of the following:

2.1. manually: from bash commandline, run

emacsclient -c -a '' -e '(my-kill-emacs)'

2.2. scripted: save the above line into an executable file à la ~/bin/shutdown_Emacs_cleanly.sh and run it. E.g.:

#!/bin/sh
emacsclient -c -a '' -e '(my-kill-emacs)'

notes

  1. If your (graphical) Emacs has no unsaved buffers when you kill it (as described above), Emacs will exit with no prompts. If your Emacs has unsaved buffers when you kill it, you will get prompts (from your character-mode Emacs in tty1) to save the buffers. (Writing a function that saves all unsaved buffers without any prompts is left as an exercise for the reader :-)

  2. Whether or not you have unsaved buffers, when your tty1 commandline exits, its terminal handling may be "polluted": e.g. (and in roughly decreasing order of importance),

    • You will no longer see what you type at the bash prompt.

    • History browsing (via up/down-arrow key) also fails--at least, I cannot see anything on the commandline.

    • Hitting RET at the bash prompt no longer does a line feed, though it still produces a new prompt. This results in a display like

      me@it:~$ me@it:~$ me@it:~$ me@it:~$ me@it:~$ me@it:~$ me@it:~$ me@it:~$ me@it:~$

    My tty1 is always polluted by running the above; YMMV. Fortunately, as Nawaz points out, one can unpollute by calling reset from the tty1 commandline (after installing package=ncurses-bin).

1 Answer 1

5

When you run (server-start) it adds a function called server-kill-emacs-query-function (defined in server.el) to the kill-emacs-query-functions hook. One solution that might work for you (I've tested it and it works for me) is to modify your emacsclient line to

emacsclient -c -a '' \
-e '(let (kill-emacs-query-functions confirm-kill-emacs kill-emacs-hook) (save-buffers-kill-emacs))'

Or better yet, define a function in your .emacs or init.el and call it from emacsclient:

(defun my-kill-emacs ()
  "Set kill-emacs-query-functions , confirm-kill-emacs , and
kill-emacs-hook to nil to quit emacs without any pesky prompts
(except to save buffers)"
  (let (kill-emacs-query-functions confirm-kill-emacs kill-emacs-hook)
    (save-buffers-kill-emacs)))

Your script:

#!/bin/sh
emacsclient -c -a '' -e '(my-kill-emacs)'

If running the above messes up your terminal, just type "reset" (part of Debian package=ncurses-bin).

5
  • The good news: reset WFM, thanks! The bad news ...
    – TomRoche
    Nov 19, 2015 at 21:34
  • ... currently, running (my-kill-emacs) from my init.el seems to auto-answer the "wanna kill clients?" question, since I don't see that. But I still get and must interact reply to the "wanna exit?" question (followed by terminal pollution, solved by reset). Dunno if this is a version problems; FWIW I currently run GNU Emacs 24.4.1 (x86_64-pc-linux-gnu, GTK+ Version 3.14.5). Meanwhile, I'll try the commandlines.
    – TomRoche
    Nov 19, 2015 at 21:38
  • I also still get and must reply to the "wanna exit?" question (followed by terminal pollution) with either of the commandlines emacsclient -c -a '' -e '(my-kill-emacs)' and emacsclient -c -a '' -e '(let (kill-emacs-query-functions confirm-kill-emacs) (save-buffers-kill-emacs))'. FWIW, I'm also running lsb_release -ds==LMDE 2 Betsy, cat /etc/debian_version==8.2, uname -rv==3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt11-1+deb8u3 (2015-08-04)
    – TomRoche
    Nov 19, 2015 at 21:56
  • Can you see if adding kill-emacs-hook to the list of let variables fixes the problem? Nov 20, 2015 at 17:29
  • That works! Edited above (pending peer review) and I'll also edit my solution below.
    – TomRoche
    Nov 22, 2015 at 5:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.