bug#81504: [PATCH] Restore current buffer after clone-indirect-buffer-hook errors
Donjuanplatinum via "Bug reports for GNU Emacs, the Swiss army knife of text editors" <[email protected]>
| Newsgroups | gmane.emacs.bugs |
|---|---|
| Message-ID | <[email protected]> |
Version: 31.0.50
Base-Commit: 810e9d675ba484dabade1a9f30201d2848c5e2ea
In `make-indirect-buffer` with clone argument, if
`clone-indirect-buffer-hook` return an error, `current-buffer` will not
be restored.
To make the error in emacs -Q:
(progn
(generate-new-buffer "base")
(with-current-buffer "base" (insert "text"))
(set-buffer "base")
(let ((clone-indirect-buffer-hook
(list (lambda () (error "hook error")))))
(condition-case nil
(make-indirect-buffer "base" "ind" t)
(error nil)))
(buffer-name (current-buffer)))
Expected: "base"
But get: "ind"
The Clone path in Fmake_indirect_buffer use set_buffer_internal_1 to
restore the current-buffer, but when clone-indirect-buffer-hook return
an error, it will skip the set_buffer_internal_1.
The attached patch replaces it with record_unwind_current_buffer so that
it will following the standard specpdl pattern to restore the current-buffer.
0001-Restore-current-buffer-after-clone-indirect-buffer-h.patch
(text/x-patch, 3.2 KB)
From 89ce33acdd96a76f6efb831183349ea7d3be406f Mon Sep 17 00:00:00 2001 From: Donjuanplatinum <[email protected]> Date: Tue, 28 Jul 2026 01:25:56 +0800 Subject: [PATCH] Restore current buffer after clone-indirect-buffer-hook errors When the CLONE argument is non-nil, Fmake_indirect_buffer switches to the new indirect buffer and runs clone-indirect-buffer-hook. If the hook return an error, the set_buffer_internal_1 restore is skipped, so current_buffer pointing to the indirect buffer. Use record_unwind_current_buffer to ensure the original buffer can be restored in normal and error paths. * src/buffer.c (Fmake_indirect_buffer): Replace set_buffer_internal_1 to specpdl unwind in the clone path. * test/src/buffer-tests.el (test-make-indirect-buffer-clone-hook): Add this condition test. --- src/buffer.c | 8 ++++++-- test/src/buffer-tests.el | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index 0a2bff27c11..423c0ce7905 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -937,7 +937,9 @@ DEFUN ("make-indirect-buffer", Fmake_indirect_buffer, Smake_indirect_buffer, } else { - struct buffer *old_b = current_buffer; + /* Arrange for the current buffer to be restored later, + even if an exit occurs. */ + specpdl_ref count = SPECPDL_INDEX (); clone_per_buffer_values (b->base_buffer, b); bset_filename (b, Qnil); @@ -946,6 +948,7 @@ DEFUN ("make-indirect-buffer", Fmake_indirect_buffer, Smake_indirect_buffer, bset_backed_up (b, Qnil); bset_local_minor_modes (b, Qnil); bset_auto_save_file_name (b, Qnil); + record_unwind_current_buffer (); set_buffer_internal_1 (b); Fset (Qbuffer_save_without_query, Qnil); Fset (Qbuffer_file_number, Qnil); @@ -955,7 +958,8 @@ DEFUN ("make-indirect-buffer", Fmake_indirect_buffer, Smake_indirect_buffer, variable copies for list variables that might be mangled due to destructive operations in the indirect buffer. */ run_hook (Qclone_indirect_buffer_hook); - set_buffer_internal_1 (old_b); + /* Restore the original buffer. */ + unbind_to (count, Qnil); } run_buffer_list_update_hook (b); diff --git a/test/src/buffer-tests.el b/test/src/buffer-tests.el index 3fae18011fb..fc6ba43b3d7 100644 --- a/test/src/buffer-tests.el +++ b/test/src/buffer-tests.el @@ -1478,6 +1478,23 @@ test-make-indirect-buffer-1 (kill-buffer indirect)))))) +(ert-deftest test-make-indirect-buffer-clone-hook () + (let ((base-buf (generate-new-buffer "base"))) + (unwind-protect + (progn + (with-current-buffer base-buf + (insert "sample text")) + (set-buffer base-buf) + (let ((clone-indirect-buffer-hook + (list (lambda () + (error "clone hook error"))))) + (should-error + (make-indirect-buffer base-buf "indirect" t))) + (should (eq (current-buffer) base-buf))) + (ignore-errors (kill-buffer "indirect")) + (when (buffer-live-p base-buf) + (kill-buffer base-buf))))) + ;; +==========================================================================+ ;; | buffer-swap-text -- 2.55.0