8

I often find myself with an incomplete or invalid emacs config, which breaks the normal behavior of kill-emacs such that it stops at an error.

In this case, I would like to forcefully kill emacs, without resorting to hunting down the PID and issuing a kill from the shell. Can I do this in pure Emacs Lisp?

PythonNut
  • 10,243
  • 2
  • 29
  • 75
  • I'm not sure I follow. If `kill-emacs` doesn't work other elisp approaches may also be fouled up, as they probably end up calling `kill-emacs` one way or another. What error do you get? It may be easier to fix the error. – Tyler Dec 16 '14 at 20:37
  • I mean, you could create a function that calls `kill -9` on the current Emacs pid for instance. You'd have to be very messed up to break that. – PythonNut Dec 16 '14 at 20:38
  • 5
    You can try setting [`kill-emacs-hook`](http://www.gnu.org/software/emacs/manual/html_node/elisp/Killing-Emacs.html) to `nil` before calling `kill-emacs`. You can also get Emacs's pid using [`emacs-pid`](http://www.gnu.org/software/emacs/manual/html_node/elisp/System-Environment.html#System-Environment) and make it commit suicide by calling `call-process` with "`kill -9`". – Constantine Dec 16 '14 at 20:43
  • 1
    if you don"t want to hunt the PID, still, there is pkill & pgrep :\ – Nsukami _ Dec 16 '14 at 21:05
  • I've run into this problem as well when updating Yasnippet with `yas-global-mode` active. For every buffer that's used (even the minibuffer), `yas-minor-mode` is turned on and errors out. Note that this means the minibuffer can't be used, but you could still possibly use `eval-last-sexp`. – Sean Allred Dec 16 '14 at 21:10
  • I run multiple instances of emacs, so `pkill` will kill them all (which I don't want) and `pgrep` won't tell me which one is the one I want to kill. – PythonNut Dec 16 '14 at 21:10
  • 1
    Unrelated, but you might want to avoid running multiple sessions of emacs – Sean Allred Dec 16 '14 at 21:11
  • @Constantine that works very well, if you can make an answer (even a minimal one), I'll accept it. – PythonNut Dec 16 '14 at 21:16

3 Answers3

15

You can try setting kill-emacs-hook to nil before calling kill-emacs:

(defun really-kill-emacs ()
  "Like `kill-emacs', but ignores `kill-emacs-hook'."
  (interactive)
  (let (kill-emacs-hook)
    (kill-emacs)))

Alternatively, you can get Emacs's PID using emacs-pid and make it commit suicide by calling call-process with "kill -9":

(defun brutally-kill-emacs ()
  "Use `call-process' to send ourselves a KILL signal."
  (interactive)
  (call-process "kill" nil nil nil "-9" (number-to-string (emacs-pid))))
Constantine
  • 9,072
  • 1
  • 34
  • 49
  • 3
    Not a critique of the answer, just additional information: note that using signal nine (the `-9` in `kill -9`) will orphan any processes that emacs has spawned, just as it would happen if emacs were a simple shell script.. – Sean Allred Dec 16 '14 at 22:29
  • Although TERM often fails to kill emacs in a broken state. So it may be the only thing. – PythonNut Dec 16 '14 at 23:22
  • When I call this way: `emacsclient -e "(really-kill-emacs)"` it kills it. But when I run it again, it try to kill already killed emacs, which leads to print out log of `emacsclient` ending with `Emacs daemon should have started, trying to connect again`@Constantine – alper Jul 19 '20 at 20:26
1

Sometimes, I end up with several unreachable emacs processes laying around. My emacsclient normally automatically starts an emacs and calls server-start--I guess there is some bug in my configuration somewhere which results in this happening more than once.

I kill the extra emacsen with killall emacs in a shell. So far, -9 hasn't been needed. (It works when there's only one emacs running, too, and I don't have to hunt down a pid!)

daveloyall
  • 1,280
  • 9
  • 21
  • Sometimes, when emacs hangs completely, a `-9` is needed. Of course, this means that emacs won't be able to commit suicide, but I'm adding it just in case. – PythonNut Dec 22 '14 at 19:30
  • This was the only thing that worked for me after an `ein:jupyter-notebook` was preventing all other methods. I guess is was hanging somewhere, but I had already ended all Python processes and killed all buffers. – n1k31t4 Nov 07 '17 at 08:31
0

This will force kill emacs daemon from bash. If there is no emacs running and when we run emacsclient -e "(kill-emacs)", which starts emacs and kills it again. I just added simple if/else to prevent that.

  • Instead of kill-emacs you can use brutally-kill-emacs () that is defined in @Constantine's answer.
#!/bin/bash

num=$(ps aux | grep -E "[e]macs --daemon" | wc -l)
if [ $num -ge 1 ]; then
    emacsclient -e "(brutally-kill-emacs)" > /dev/null 2>&1

    # following commands guarantees 
    kill -9 $(ps aux | grep -E "emacs"      | awk '{print $2}')
    (killall emacs) > /dev/null 2>&1
    (killall emacsclient) > /dev/null 2>&1
    kill -9 $(ps aux | grep -E "[e]macs" | awk '{print $2}') > /dev/null 2>&1
else
    echo "emacs is already killed."
fi


----

If you are a m

Sometimes following zombie process remain opened and consumes all the memory so `kill -9 $(ps aux | grep -E "emacs" | awk '{print $2}')` will be your friend.


alper 4785 100.0 0.0 4461068 7860 ?? R 1:27AM 41:42.43 /usr/local/Cellar/emacs-head@26/26.3_1/Emacs.app/Contents/MacOS/Emacs -Q -l /Users/alper/.emacs.d/elpa/async-20200809.501/async.elc -batch -f async-batch-invoke

alper
  • 1,238
  • 11
  • 30