* lisp/org-clock.el (org-clock-kill-emacs-query): Wrap the `org-clock-out'
and `save-buffer' calls in `condition-case', reporting any error instead of
letting it escape the hook.
`org-clock-kill-emacs-query' runs from `kill-emacs-query-functions', where a
non-nil return value is what allows the exit to proceed. The function ends
with an unconditional t and a comment saying so, but `org-clock-out' is
called without its FAIL-QUIETLY argument, so any error it signals propagates
out of the hook and that t is never reached. Emacs then refuses to exit.
The error seen in practice is "Clock start time is gone", which
`org-clock-out' signals when `org-clock-marker' no longer sits on its CLOCK
line. The marker survives ordinary editing, but it does not survive having
the region that contains the CLOCK line replaced wholesale -- `org-sort-entries'
on the clocked tree does this, and so does reverting a buffer whose changed
span brackets the line. The user is then stuck: answering "yes" at the
prompt fails and cancels the exit, and only answering "no" gets out.
Recipe, in emacs -Q:
(setq org-clock-persist nil
org-clock-auto-clock-resolution nil)
;; in an Org buffer with a "** TASK banana" heading
(org-clock-in)
;; now invalidate the marker the way a wholesale replacement does
(let ((text (buffer-string)))
(erase-buffer)
(insert "* New heading\n" text))
(org-clock-kill-emacs-query) ; => signals, so C-x C-c would be refused
With this change the same recipe returns t and reports "Could not clock out:
Clock start time is gone" in the echo area.
Note this only guarantees that a lost marker cannot trap the user in a
session; it does not attempt to keep the marker in sync, which is the larger
issue behind the "Clock start time is gone" reports going back to 2017.
TINYCHANGE
---
lisp/org-clock.el | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/lisp/org-clock.el b/lisp/org-clock.el
index 75ecb1b..7c53b52 100644
--- a/lisp/org-clock.el
+++ b/lisp/org-clock.el
@@ -3353,8 +3353,14 @@ This function is added to `kill-emacs-query-functions'."
(let ((buf (org-clocking-buffer)))
(when (and buf (yes-or-no-p "Clock out before exiting? "))
(with-current-buffer buf
- (org-clock-out)
- (save-buffer))))
+ ;; Do not let a failure here abort `kill-emacs'. In particular,
+ ;; `org-clock-marker' may no longer sit on its CLOCK line, and
+ ;; `org-clock-out' then signals "Clock start time is gone".
+ (condition-case err
+ (progn (org-clock-out) (save-buffer))
+ (error
+ (message "Could not clock out: %s" (error-message-string err))
+ (sit-for 2))))))
;; Unconditionally return t for `kill-emacs-query-functions'.
t)
--
2.44.0