From 89f54e81576d9d9e35b67e7c5831495c4bb444c5 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Fri, 16 Dec 2022 16:29:51 +0200 Subject: [PATCH] A better fix for bug#60096 * lisp/startup.el (initial-scratch-message): * lisp/simple.el (get-scratch-buffer-create): Revert last changes. * src/window.c (Fset_window_configuration): Force recalculation of Vwindow_list after restoring the windows. * src/buffer.c (other_buffer_safely): Make sure we always return a valid buffer, even if 'get-scratch-buffer-create' signals an error. --- lisp/simple.el | 7 +------ lisp/startup.el | 2 +- src/buffer.c | 13 ++++++++++++- src/window.c | 10 +++++++++- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/lisp/simple.el b/lisp/simple.el index dcc2242e49f..654b56a0886 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -10683,12 +10683,7 @@ too short to have a dst element. ;; we just created it. (with-current-buffer scratch (when initial-scratch-message - ;; We used to run this through substitute-command-keys, - ;; but that might be unsafe in some rare cases, and this - ;; function must never fail and signal an error, because - ;; it is called from other_buffer_safely, which must - ;; always produce a valid buffer. - (insert initial-scratch-message) + (insert (substitute-command-keys initial-scratch-message)) (set-buffer-modified-p nil)) (funcall initial-major-mode)) scratch))) diff --git a/lisp/startup.el b/lisp/startup.el index 7f8e8d55db8..6270de2ace6 100644 --- a/lisp/startup.el +++ b/lisp/startup.el @@ -1669,7 +1669,7 @@ Changed settings will be marked as \"CHANGED outside of Customize\"." (defcustom initial-scratch-message (purecopy "\ ;; This buffer is for text that is not saved, and for Lisp evaluation. -;; To create a file, visit it with \"C-x C-f\" and enter text in its buffer. +;; To create a file, visit it with \\[find-file] and enter text in its buffer. ") "Initial documentation displayed in *scratch* buffer at startup. diff --git a/src/buffer.c b/src/buffer.c index 9a30faa0e1a..443f90ff894 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1747,7 +1747,18 @@ other_buffer_safely (Lisp_Object buffer) if (candidate_buffer (buf, buffer)) return buf; - return safe_call (1, Qget_scratch_buffer_create); + /* This function must return a valid buffer, since it is frequently + our last line of defense in the face of the expected buffers + becoming dead under our feet. safe_call below could return nil + if recreating *scratch* in Lisp, which does some fancy stuff, + signals an error in some weird use case. */ + buf = safe_call (1, Qget_scratch_buffer_create); + if (NILP (buf)) + { + AUTO_STRING (scratch, "*scratch*"); + buf = Fget_buffer_create (scratch, Qnil); + } + return buf; } DEFUN ("buffer-enable-undo", Fbuffer_enable_undo, Sbuffer_enable_undo, diff --git a/src/window.c b/src/window.c index f116b9a9d72..90fa6ac2dfe 100644 --- a/src/window.c +++ b/src/window.c @@ -2639,7 +2639,7 @@ window_list (void) Lisp_Object arglist = Qnil; /* We are visiting windows in canonical order, and add - new windows at the front of args[1], which means we + new windows at the front of arglist, which means we have to reverse this list at the end. */ foreach_window (XFRAME (frame), add_window_to_list, &arglist); arglist = Fnreverse (arglist); @@ -7329,6 +7329,14 @@ the return value is nil. Otherwise the value is t. */) last_selected_window) = selected_window; + /* We may have deleted windows above. Then again, maybe we + haven't: the functions we call to maybe delete windows can + decide a window cannot be deleted. Force recalculation of + Vwindow_list next time it is needed, to make sure stale + windows with no buffers don't escape into the wild, which + will cause crashes elsewhere. */ + Vwindow_list = Qnil; + if (NILP (data->focus_frame) || (FRAMEP (data->focus_frame) && FRAME_LIVE_P (XFRAME (data->focus_frame)))) -- 2.39.2