Subject: Re: bug#47244: 28.0.50; SIGSEGV in long-runnning Emacs

From: Michael Welsh Duggan <[email-masked]>
Date: Tue, 06 Apr 2021 10:40:56 -0400

martin rudalics <[email-masked]> writes:

>> Actually, what I did is use xbuffer, which as part of it outputs the
>> name_.  For example:
>>
>> (gdb) p w->contents
>> $53 = XIL(0x5555578be555)
>> (gdb) xbuffer
>> $54 = (struct buffer *) 0x5555578be550
>> 0x555557241db0 "build.ninja"
>>
>> In this case the name_ field is "build.ninja".  The definition of
>> xbuffer is:
>
> OK.  But please let me reassess what you said earlier:
>
>> There were three
>> frames that we looped over in the FOR_EACH_FRAME() loop.  Of these, only
>> the first is interesting.  In this case window_list_1() in window_loop()
>> returned three windows.  For each window, in the
>> REPLACE_BUFFER_IN_WINDOWS_SAFELY case branch, EQ (w->contents, obj)
>> returned false.
>
> So if one of these three windows on the first frame shows (showed)
> "build.ninja" then what do (did) the other two windows show?

I was somewhat incorrect.  The first frame has two windows: build.ninja
and a minibuffer.  See below for more.

>> As a result, best_window is Qnil at the end, and
>> replace-buffer_in_windows_safely_count never gets incremented.  For the
>> other two frames the return value of window_list_1() was Qnil.
>
> The latter could be another problem but should not concern us for the
> moment - do these frames get killed in the course?

The two frames that returned no windows were the invisible daemon frame
"F1" and the frame containing the window containing the "*Server*"
buffer.

>> When window_list_1() gets called with the window that has "*Server*" as
>> the buffer, window_list() (as called on line 2866) does not return a
>> list that contains that window.  I do not know how Vwindow_list (which
>> is what is returned by window_list() gets updated.
>
> Vwindow_list is a cache of the list of all windows and is (re-)built by
> window_list when it is nil.  It is set to nil (that is, the cache gets
> invalidated) whenever a window is deleted or created.  What is the value
> of Vwindow_list when window_list_1() gets called with the window that
> has "*Server*" as the buffer?

Here is the state as I've been able to determine from the debugger:

Vframe_list contains three entries: "build.ninja", "*Server*", and
"F1".  This matches reality.  "F1" is the invisible frame created by
--daemon.

Frame "build.ninja" has a selected_window whose contents are the buffer
"build.ninja".

Frame "*Server*" has a selected_window whose contents are the buffer
"*Server*".

Frame "F1" has a selected_window whose contents are the buffer
"*scratch*".

Vwindow_list contains two entries: A window whose contents are
"build.ninja", and a window whose contents are " *Minibuf-0*".

Importantly, Vwindow_list does not contain the window whose contents are
"*Server*".  Since the window_list_1() call uses the value of
Vwindow_list to create its result, the loop in window_loop() will never
compare EQ in the REPLACE_BUFFER_IN_WINDOWS_SAFELY case clause.

-- 
Michael Welsh Duggan
([email-masked])