Subject: Re: bug#48337: Fwd: 28.0.50; Emacs crashing randomly (possibly minibuffer activity related)

From: Alan Mackenzie <[email-masked]>
Date: Thu, 13 May 2021 11:54:37 +0000

Hello again, Martin.

On Thu, May 13, 2021 at 09:52:19 +0000, Alan Mackenzie wrote:
> On Thu, May 13, 2021 at 09:54:52 +0200, martin rudalics wrote:
> >  > The deeper cause of the bug is that calling buffer-list-update-hook
> >  > simply doesn't belong in record-window-buffer.  That hook should be
> >  > called when the buffer list changes, not when a window's current buffer
> >  > gets "recorded".

> >  > So, as the main fix, I propose moving the call of buffer-list-update-hook
> >  > to (some of) the places where record-window-buffer gets called, those
> >  > places where the buffer list changes.  There are exactly two such places,
> >  > both in window.c.  This will prevent the chain of events in read_minibuf
> >  > outlined above.

> > Alan, please take one step back and reconsider.  IIUC you added the
> > `record-window-buffer' call to read_minibuf, added the DO-MINIBUF
> > argument to `record-window-buffer' and now decide that
> > `buffer-list-update-hook' doesn't belong into `record-window-buffer'.

> > Aren't you putting the cart before the horse?  That decision might be
> > correct but still constitutes a change that affects all applications
> > running `buffer-list-update-hook'.

> Maybe you're right.  I've never really liked those changes to
> record-window-buffer, they're a bit scruffy.  The requirement is simply
> to push a minibuffer onto w->prev_buffers, where w is the mini-window of
> a frame.

> Maybe I should instead undo those changes to r-w-b, and write a separate
> function for pushing the minibuffer onto w->prev_buffers.  This would
> surely be cleaner.  Whether that function should be in C or in Lisp
> (like record-window-buffer) would need to be decided.  Maybe r-w-b could
> use that new function to avoid duplicating code.

How about the following functions, in which minibuf.c now bypasses
record-window-buffer, instead calling push-window-buffer-onto-prev
direct?  I'm still not convinced that the call to
buffer-list-update-hooks belongs in record-window-buffer, but that
doesn't seem too important any more.  On preliminary testing, these
appear to work:

(defun push-window-buffer-onto-prev (&optional window)
  "Push entry for WINDOW's buffer onto WINDOW's prev-buffers list.
WINDOW must be a live window and defaults to the selected one.

Any duplicate entries for the buffer in the list are removed."
  (let* ((window (window-normalize-window window t))
         (buffer (window-buffer window))
         (w-list (window-prev-buffers window))
         (entry (assq buffer w-list)))
    (when entry
      (setq w-list (assq-delete-all buffer w-list)))
    (let ((start (window-start window))
          (point (window-point window)))
      (setq entry
            (cons buffer
                  (if entry
                      ;; We have an entry, update marker position.
                      (list (set-marker (nth 1 entry) start)
                            (set-marker (nth 2 entry) point))
                    (list (copy-marker start)
                          (copy-marker
                           ;; Preserve window-point-insertion-type
                           ;; (Bug#12855)
                           point (with-current-buffer buffer
                                   window-point-insertion-type))))))
      (set-window-prev-buffers window (cons entry w-list)))))

(defun record-window-buffer (&optional window)
  "Record WINDOW's buffer.
WINDOW must be a live window and defaults to the selected one.

If WINDOW is a minibuffer, it will only be recorded if DO-MINIBUF
is non-nil."
  (let* ((window (window-normalize-window window t))
         (buffer (window-buffer window)))
    ;; Reset WINDOW's next buffers.  If needed, they are resurrected by
    ;; `switch-to-prev-buffer' and `switch-to-next-buffer'.
    (set-window-next-buffers window nil)

    ;; Don't record insignificant buffers.
    (when (not (eq (aref (buffer-name buffer) 0) ?\s))
      (push-window-buffer-onto-prev window)
      (run-hooks 'buffer-list-update-hook))))

> > martin

-- 
Alan Mackenzie (Nuremberg, Germany).