bug#81561: 31.0.91; speedbar-window-mode creates stale idle timers

Vincenzo Pupillo <[email protected]>
Newsgroups gmane.emacs.bugs
Message-ID <[email protected]>
Ciao Daniel,

In data mercoledì 12 agosto 2026 22:11:23 Ora legale dell’Europa centrale, 
Daniel Mendler ha scritto:
> Vincenzo Pupillo <[email protected]> writes:
> > Ciao, I wasn’t able to reproduce the problem reported by Daniel. The only
> > way was to kill the 'speedbar-buffer' process. So I added a
> > 'kill-buffer-hook' to handle this event. I also eliminated a few other
> > causes of  stale idle timers.
> > 
> > @Daniel, could you please try this patch?
> 
> Would it make sense to instead move the (with-current-buffer
> speedbar-buffer ...) into speedbar-set-timer instead of replicating it
> so often?
That's right, I added the calls to 'with-current-buffer' one at a time, but in 
the end, it's needed everywhere...

Attached is the new version of the patch.
> 
> Daniel

Thanks.
Vincenzo
0001-Handle-speedbar-buffer-kill-when-in-speedbar-window-.patch (text/x-patch, 4 KB)
From 344f25607d8ce81f9bed7b7ce647fa227d5f5d7c Mon Sep 17 00:00:00 2001
From: Vincenzo Pupillo <[email protected]>
Date: Wed, 12 Aug 2026 18:11:25 +0200
Subject: [PATCH] Handle 'speedbar-buffer' kill when in 'speedbar-window-mode'.

This patch handle the DFRAME TIMER ERROR reported by Daniel
Mendler (bug#81561). In addition, it eliminates other causes
of stale idle timers.

* lisp/speedbar.el
(speedbar-window-mode): Added a 'kill-buffer' handler. Removed a
unnecessary 'speedbar-mode' invocation.
(speedbar-window--close): New optional parameter used bye the
'kill-buffer' handler for 'speedbar-buffer'.
(speedbar-set-timer): Make sure that 'speedbar-set-timer' is called in
'speedbar-buffer', this prevents the creation of stale idle timers.
(speedbar--speedbar-live-p): Make sure that 'speedbar-buffer' is still
live.
---
 lisp/speedbar.el | 37 ++++++++++++++++++++++---------------
 1 file changed, 22 insertions(+), 15 deletions(-)

diff --git a/lisp/speedbar.el b/lisp/speedbar.el
index 3e965d4286c..778c5f5f12f 100644
--- a/lisp/speedbar.el
+++ b/lisp/speedbar.el
@@ -1083,7 +1083,6 @@ speedbar-window-mode
 	    speedbar-last-selected-file nil)
 
       (set-buffer speedbar-buffer)
-      (speedbar-mode)
 
       ;; let's create the window
       (setq speedbar--window
@@ -1102,14 +1101,19 @@ speedbar-window-mode
       (speedbar-update-contents)
       (speedbar-set-timer dframe-update-speed)
 
+      ;; handle kill-buffer
+      (add-hook 'kill-buffer-hook (lambda () (speedbar-window--close t)) nil t)
+
       ;; hscroll
       (setq-local auto-hscroll-mode nil)
       ;; reset the selection variable
       (setq speedbar-last-selected-file nil)
       (select-window current-window))))
 
-(defun speedbar-window--close ()
-  "Close `speedbar-window'."
+(defun speedbar-window--close (&optional no-kill-buffer)
+  "Close `speedbar-window'.
+When NO-KILL-BUFFER is not nil, close window without killing
+'speedbar-buffer', which is useful for 'kill-buffer-hook'."
   (when (speedbar-window--live-p)
     (let ((current-window (selected-window)))
       ;; store the current window width
@@ -1123,10 +1127,11 @@ speedbar-window--close
       (setq speedbar--window nil
 	    speedbar-frame nil
 	    dframe-attached-frame nil)
-      (with-current-buffer speedbar-buffer
-        (speedbar-set-timer nil))
-      (kill-buffer speedbar-buffer)
-      (setq speedbar-buffer nil)
+
+      (speedbar-set-timer nil)
+      (unless no-kill-buffer
+        (kill-buffer speedbar-buffer)
+        (setq speedbar-buffer nil))
       (when (and current-window (window-live-p current-window))
 	(select-window current-window)))))
 
@@ -2724,13 +2729,15 @@ speedbar-set-timer
   "Set up the speedbar timer with TIMEOUT.
 Uses `dframe-set-timer'.
 Also resets scanner functions."
-  (dframe-set-timer timeout 'speedbar-timer-fn 'speedbar-update-flag)
-  ;; Apply a revert hook that will reset the scanners.  We attach to revert
-  ;; because most reverts occur during VC state change, and this lets our
-  ;; VC scanner fix itself.
-  (if timeout
-      (add-hook 'after-revert-hook 'speedbar-reset-scanners)
-    (remove-hook 'after-revert-hook 'speedbar-reset-scanners))
+  ;; `dframe-set-timer' must be called from `speedbar-buffer'.
+  (with-current-buffer speedbar-buffer
+    (dframe-set-timer timeout 'speedbar-timer-fn 'speedbar-update-flag)
+    ;; Apply a revert hook that will reset the scanners.  We attach to revert
+    ;; because most reverts occur during VC state change, and this lets our
+    ;; VC scanner fix itself.
+    (if timeout
+        (add-hook 'after-revert-hook 'speedbar-reset-scanners)
+      (remove-hook 'after-revert-hook 'speedbar-reset-scanners)))
   ;; change this if it changed for some reason
   (speedbar-set-mode-line-format))
 
@@ -2740,7 +2747,7 @@ speedbar--speedbar-live-p
    ((and (speedbar-current-frame)
 	 (frame-live-p (speedbar-current-frame)))
     t)
-   ((speedbar-window--window-live-p) t)
+   ((speedbar-window--live-p) t)
    (t nil)))
 
 (defun speedbar-timer-fn ()
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.