radian-software / apheleia

🌷 Run code formatter on buffer contents without moving point, using RCS patches and dynamic programming.
MIT License
570 stars 81 forks source link

Error: "Selecting deleted buffer" #123

Closed gsingh93 closed 2 years ago

gsingh93 commented 2 years ago

I'm getting the following backtrace whenever I accept a prompt about adding safe local variables to my customizations file:

Debugger entered--Lisp error: (error "Selecting deleted buffer")
  set-buffer(#<killed buffer>)
  (save-current-buffer (set-buffer cur-buffer) (if (equal apheleia--buffer-hash (apheleia--buffer-hash)) (progn (apheleia--apply-rcs-patch (current-buffer) patch-buffer) (if callback (progn (funcall callback))))))
  (closure ((formatted-buffer . #<killed buffer>) (remote) (cur-buffer . #<killed buffer>) (formatters lisp-indent) (callback closure ((formatters lisp-indent) t) nil (condition-case err (progn (if buffer-file-name (progn ...)) (run-hooks 'apheleia-post-format-hook)) ((debug error) (message "Apheleia: %s" err) nil))) (formatter lisp-indent) t) (patch-buffer) (save-current-buffer (set-buffer cur-buffer) (if (equal apheleia--buffer-hash (apheleia--buffer-hash)) (progn (apheleia--apply-rcs-patch (current-buffer) patch-buffer) (if callback (progn (funcall callback)))))))(#<buffer  *apheleia-diff-stdout*-262844>)
  funcall((closure ((formatted-buffer . #<killed buffer>) (remote) (cur-buffer . #<killed buffer>) (formatters lisp-indent) (callback closure ((formatters lisp-indent) t) nil (condition-case err (progn (if buffer-file-name (progn ...)) (run-hooks 'apheleia-post-format-hook)) ((debug error) (message "Apheleia: %s" err) nil))) (formatter lisp-indent) t) (patch-buffer) (save-current-buffer (set-buffer cur-buffer) (if (equal apheleia--buffer-hash (apheleia--buffer-hash)) (progn (apheleia--apply-rcs-patch (current-buffer) patch-buffer) (if callback (progn (funcall callback))))))) #<buffer  *apheleia-diff-stdout*-262844>)
  (progn (funcall callback stdout))
  (if callback (progn (funcall callback stdout)))
  (if exit-ok (if callback (progn (funcall callback stdout))) (message (concat "Failed to run %s: exit status %s " "(see %s %s)") (car command) proc-exit-status (if (string-prefix-p " " log-name) "hidden buffer" "buffer") (string-trim log-name)))
  (unwind-protect (if exit-ok (if callback (progn (funcall callback stdout))) (message (concat "Failed to run %s: exit status %s " "(see %s %s)") (car command) proc-exit-status (if (string-prefix-p " " log-name) "hidden buffer" "buffer") (string-trim log-name))) (if ensure (progn (funcall ensure))) (condition-case nil (progn (kill-buffer stdout)) (error nil)) (condition-case nil (progn (kill-buffer stderr)) (error nil)))
  (let ((exit-ok (funcall (or exit-status #'zerop) proc-exit-status))) (if (and exit-ok apheleia-log-only-errors) nil (save-current-buffer (set-buffer (get-buffer-create log-name)) (special-mode) (save-restriction (widen) (let ((inhibit-read-only t) (orig-point (point)) (keep-at-end (eobp)) (stderr-string (save-current-buffer ... ...))) (goto-char (point-max)) (skip-chars-backward "\n") (delete-region (point) (point-max)) (if (bobp) nil (insert "\n\n\f\n")) (if exit-ok nil (if apheleia--last-error-marker nil (setq apheleia--last-error-marker ...) (move-marker apheleia--last-error-marker ...))) (insert (current-time-string) " :: " (buffer-local-value 'default-directory stdout) "\n$ " (mapconcat #'shell-quote-argument command " ") "\n\n" (if (string-empty-p stderr-string) "(no output on stderr)" stderr-string) "\n\n" "Command " (if exit-ok "succeeded" "failed") " with exit code " (number-to-string proc-exit-status) ".\n") (goto-char (if keep-at-end (point-max) (min ... orig-point))) (goto-char (point-max)))))) (if formatter (progn (run-hook-with-args 'apheleia-formatter-exited-hook :formatter formatter :error (not exit-ok) :log (get-buffer log-name)))) (unwind-protect (if exit-ok (if callback (progn (funcall callback stdout))) (message (concat "Failed to run %s: exit status %s " "(see %s %s)") (car command) proc-exit-status (if (string-prefix-p " " log-name) "hidden buffer" "buffer") (string-trim log-name))) (if ensure (progn (funcall ensure))) (condition-case nil (progn (kill-buffer stdout)) (error nil)) (condition-case nil (progn (kill-buffer stderr)) (error nil))))
  (closure ((log-name . "*apheleia-diff-log*") (stderr . #<buffer  *apheleia-diff-stderr*-190207>) (stdout . #<buffer  *apheleia-diff-stdout*-262844>) (name . "diff") (formatter) (exit-status closure ((run-on-remote) (clear-files) (new-fname) (old-fname . "/Users/gsgx/.emacs.d/personal/custom...") (callback closure ... ... ...) (remote) (new-buffer . #<killed buffer>) (old-buffer . #<killed buffer>) t) (status) (memq status '...)) (ensure closure ((run-on-remote) (clear-files) (new-fname) (old-fname . "/Users/gsgx/.emacs.d/personal/custom...") (callback closure ... ... ...) (remote) (new-buffer . #<killed buffer>) (old-buffer . #<killed buffer>) t) nil (let (...) (while --dolist-tail-- ...))) (callback closure ((formatted-buffer . #<killed buffer>) (remote) (cur-buffer . #<killed buffer>) (formatters lisp-indent) (callback closure ... nil ...) (formatter lisp-indent) t) (patch-buffer) (save-current-buffer (set-buffer cur-buffer) (if ... ...))) (remote) (stdin . #<killed buffer>) (command "diff" "--rcs" "--strip-trailing-cr" "--" "/Users/gsgx/.emacs.d/personal/custom..." "-") (--cl-rest-- :command ("diff" "--rcs" "--strip-trailing-cr" "--" "/Users/gsgx/.emacs.d/personal/custom..." "-") :stdin #<killed buffer> :callback (closure (... ... ... ... ... ... t) (patch-buffer) (save-current-buffer ... ...)) :remote nil :ensure (closure (... ... ... ... ... ... ... ... t) nil (let ... ...)) :exit-status (closure (... ... ... ... ... ... ... ... t) (status) (memq status ...))) t) (proc-exit-status) (let ((exit-ok (funcall ... proc-exit-status))) (if (and exit-ok apheleia-log-only-errors) nil (save-current-buffer (set-buffer ...) (special-mode) (save-restriction ... ...))) (if formatter (progn (run-hook-with-args ... :formatter formatter :error ... :log ...))) (unwind-protect (if exit-ok (if callback ...) (message ... ... proc-exit-status ... ...)) (if ensure (progn ...)) (condition-case nil (progn ...) (error nil)) (condition-case nil (progn ...) (error nil)))))(0)
  funcall((closure ((log-name . "*apheleia-diff-log*") (stderr . #<buffer  *apheleia-diff-stderr*-190207>) (stdout . #<buffer  *apheleia-diff-stdout*-262844>) (name . "diff") (formatter) (exit-status closure ((run-on-remote) (clear-files) (new-fname) (old-fname . "/Users/gsgx/.emacs.d/personal/customizations.el") (callback closure ((formatted-buffer . #<killed buffer>) (remote) (cur-buffer . #<killed buffer>) (formatters lisp-indent) (callback closure ... nil ...) (formatter lisp-indent) t) (patch-buffer) (save-current-buffer (set-buffer cur-buffer) (if ... ...))) (remote) (new-buffer . #<killed buffer>) (old-buffer . #<killed buffer>) t) (status) (memq status '(0 1))) (ensure closure ((run-on-remote) (clear-files) (new-fname) (old-fname . "/Users/gsgx/.emacs.d/personal/customizations.el") (callback closure ((formatted-buffer . #<killed buffer>) (remote) (cur-buffer . #<killed buffer>) (formatters lisp-indent) (callback closure ... nil ...) (formatter lisp-indent) t) (patch-buffer) (save-current-buffer (set-buffer cur-buffer) (if ... ...))) (remote) (new-buffer . #<killed buffer>) (old-buffer . #<killed buffer>) t) nil (let ((--dolist-tail-- clear-files)) (while --dolist-tail-- (let (...) (condition-case nil ... ...) (setq --dolist-tail-- ...))))) (callback closure ((formatted-buffer . #<killed buffer>) (remote) (cur-buffer . #<killed buffer>) (formatters lisp-indent) (callback closure ((formatters lisp-indent) t) nil (condition-case err (progn ... ...) (... ... nil))) (formatter lisp-indent) t) (patch-buffer) (save-current-buffer (set-buffer cur-buffer) (if (equal apheleia--buffer-hash (apheleia--buffer-hash)) (progn (apheleia--apply-rcs-patch ... patch-buffer) (if callback ...))))) (remote) (stdin . #<killed buffer>) (command "diff" "--rcs" "--strip-trailing-cr" "--" "/Users/gsgx/.emacs.d/personal/customizations.el" "-") (--cl-rest-- :command ("diff" "--rcs" "--strip-trailing-cr" "--" "/Users/gsgx/.emacs.d/personal/customizations.el" "-") :stdin #<killed buffer> :callback (closure ((formatted-buffer . #<killed buffer>) (remote) (cur-buffer . #<killed buffer>) (formatters lisp-indent) (callback closure (... t) nil (condition-case err ... ...)) (formatter lisp-indent) t) (patch-buffer) (save-current-buffer (set-buffer cur-buffer) (if (equal apheleia--buffer-hash ...) (progn ... ...)))) :remote nil :ensure (closure ((run-on-remote) (clear-files) (new-fname) (old-fname . "/Users/gsgx/.emacs.d/personal/customizations.el") (callback closure (... ... ... ... ... ... t) (patch-buffer) (save-current-buffer ... ...)) (remote) (new-buffer . #<killed buffer>) (old-buffer . #<killed buffer>) t) nil (let ((--dolist-tail-- clear-files)) (while --dolist-tail-- (let ... ... ...)))) :exit-status (closure ((run-on-remote) (clear-files) (new-fname) (old-fname . "/Users/gsgx/.emacs.d/personal/customizations.el") (callback closure (... ... ... ... ... ... t) (patch-buffer) (save-current-buffer ... ...)) (remote) (new-buffer . #<killed buffer>) (old-buffer . #<killed buffer>) t) (status) (memq status '(0 1)))) t) (proc-exit-status) (let ((exit-ok (funcall (or exit-status #'zerop) proc-exit-status))) (if (and exit-ok apheleia-log-only-errors) nil (save-current-buffer (set-buffer (get-buffer-create log-name)) (special-mode) (save-restriction (widen) (let (... ... ... ...) (goto-char ...) (skip-chars-backward "\n") (delete-region ... ...) (if ... nil ...) (if exit-ok nil ...) (insert ... " :: " ... "\n$ " ... "\n\n" ... "\n\n" "Command " ... " with exit code " ... ".\n") (goto-char ...) (goto-char ...))))) (if formatter (progn (run-hook-with-args 'apheleia-formatter-exited-hook :formatter formatter :error (not exit-ok) :log (get-buffer log-name)))) (unwind-protect (if exit-ok (if callback (progn (funcall callback stdout))) (message (concat "Failed to run %s: exit status %s " "(see %s %s)") (car command) proc-exit-status (if (string-prefix-p " " log-name) "hidden buffer" "buffer") (string-trim log-name))) (if ensure (progn (funcall ensure))) (condition-case nil (progn (kill-buffer stdout)) (error nil)) (condition-case nil (progn (kill-buffer stderr)) (error nil))))) 0)
  (if (process-live-p proc) nil (funcall callback (process-exit-status proc)))
  (closure ((callback closure ((log-name . "*apheleia-diff-log*") (stderr . #<buffer  *apheleia-diff-stderr*-190207>) (stdout . #<buffer  *apheleia-diff-stdout*-262844>) (name . "diff") (formatter) (exit-status closure (... ... ... ... ... ... ... ... t) (status) (memq status ...)) (ensure closure (... ... ... ... ... ... ... ... t) nil (let ... ...)) (callback closure (... ... ... ... ... ... t) (patch-buffer) (save-current-buffer ... ...)) (remote) (stdin . #<killed buffer>) (command "diff" "--rcs" "--strip-trailing-cr" "--" "/Users/gsgx/.emacs.d/personal/customization..." "-") (--cl-rest-- :command ("diff" "--rcs" "--strip-trailing-cr" "--" "/Users/gsgx/.emacs.d/personal/customization..." "-") :stdin #<killed buffer> :callback (closure ... ... ...) :remote nil :ensure (closure ... nil ...) :exit-status (closure ... ... ...)) t) (proc-exit-status) (let ((exit-ok ...)) (if (and exit-ok apheleia-log-only-errors) nil (save-current-buffer ... ... ...)) (if formatter (progn ...)) (unwind-protect (if exit-ok ... ...) (if ensure ...) (condition-case nil ... ...) (condition-case nil ... ...)))) (connection-type . pipe) (noquery . t) (remote) (command "diff" "--rcs" "--strip-trailing-cr" "--" "/Users/gsgx/.emacs.d/personal/customization..." "-") (stderr . #<buffer  *apheleia-diff-stderr*-190207>) (stdout . #<buffer  *apheleia-diff-stdout*-262844>) (stdin . #<killed buffer>) (name . "apheleia-diff") (--cl-rest-- :name "apheleia-diff" :stdin #<killed buffer> :stdout #<buffer  *apheleia-diff-stdout*-262844> :stderr #<buffer  *apheleia-diff-stderr*-190207> :command ("diff" "--rcs" "--strip-trailing-cr" "--" "/Users/gsgx/.emacs.d/personal/customization..." "-") :remote nil :connection-type pipe :noquery t :callback (closure ((log-name . "*apheleia-diff-log*") (stderr . #<buffer  *apheleia-diff-stderr*-190207>) (stdout . #<buffer  *apheleia-diff-stdout*-262844>) (name . "diff") (formatter) (exit-status closure ... ... ...) (ensure closure ... nil ...) (callback closure ... ... ...) (remote) (stdin . #<killed buffer>) (command "diff" "--rcs" "--strip-trailing-cr" "--" "/Users/gsgx/.emacs.d/personal/customization..." "-") (--cl-rest-- :command ... :stdin #<killed buffer> :callback ... :remote nil :ensure ... :exit-status ...) t) (proc-exit-status) (let (...) (if ... nil ...) (if formatter ...) (unwind-protect ... ... ... ...)))) t) (proc _event) (if (process-live-p proc) nil (funcall callback (process-exit-status proc))))(#<process apheleia-diff<1>> "finished\n")

This is my init.el:

(setq debug-on-error t)
(setq custom-file "~/.emacs.d/customizations.el")
(package-initialize)
(require 'apheleia)
(apheleia-global-mode +1)

Now create a file called foo.el with this content:

-*- flycheck-disabled-checkers: emacs-lisp-checkdoc -*-

When I open the file, I get the following message:

The local variables list in foo.el
contains values that may not be safe (*).

Do you want to apply it?  You can type
y  -- to apply the local variables list.
n  -- to ignore the local variables list.
!  -- to apply the local variables list, and permanently mark these
      values (*) as safe (in the future, they will be set automatically.)
i  -- to ignore the local variables list, and permanently mark these
      values (*) as ignored

  * flycheck-disabled-checkers : emacs-lisp-checkdoc

After pressing '!', I get the backtrace listed above (I specifically did load-file apheleia.el so that I could see an elisp backtrace instead of compiled bytecode).

elken commented 2 years ago

Does the linked PR resolve your issue?

I couldn't replicate it :sweat_smile:

gsingh93 commented 2 years ago

Does the linked PR resolve your issue?

Yes, thanks for the quick fix!

I couldn't replicate it 😅

Interestingly, this morning I couldn't replicate it either. But then it started reliably happening again. I guess this is probably some race condition with the buffer being open or killed, so maybe it makes sense that it's non-deterministic. But once it was reliably reproducing again I tested with and without the patch, and it always happened without the patch and never happened with the patch.

elken commented 2 years ago

Thanks for confirming! :D