Subject: bug#75461: 30.0.93; Frequent (but inconsistent) hangs when creating frames

From: Phil Sainty <[email-masked]>
Date: Sun, 23 Feb 2025 02:51:55 +1300

Hi Eli,

On 2025-01-10 03:18, Eli Zaretskii wrote:
> If it's an infloop, please follow the steps described in etc/DEBUG
> under "If the symptom of the bug is that Emacs fails to respond".

After attaching GDB and running 'finish' repeatedly, it looks like
it's failing to exit from redisplay_internal.  It doesn't come back
to the gdb prompt after this message:

Run till exit from #0  0x000059a26b4124af in redisplay_internal () at 
xdisp.c:17390

After repeating the process to get back to that frame, I stepped
through that function with 'next', and it's hitting the "goto 
retry_frame;"
for the "if (FRAME_GARBAGED_P (f))" condition every time:

         retry_frame:
           if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
             {
               [...]

               if (FRAME_REDISPLAY_P (f) && !FRAME_OBSCURED_P (f))
                 {
                   [...]

                   /* On some platforms (at least MS-Windows), the
                      scroll_run_hook called from scrolling_window
                      called from update_frame could set the frame's
                      garbaged flag, in which case we need to redisplay
                      the frame.  Don't do that on TTY frames, since we
                      need to keep the garbaged flag in that case when
                      the frame has been resized.  */
                   if (FRAME_GARBAGED_P (f))
                     {
                       fset_redisplay (f);
                       f->garbaged = false;
->                    goto retry_frame;
                     }
                   f->cursor_type_changed = false;
                   f->updated_p = true;
                   f->inhibit_clear_image_cache = false;
                 }
             }

By printing "f->garbaged" I can see that it's false up to the
following, and true after this call to redisplay_windows:

               if (FRAME_REDISPLAY_P (f) && !FRAME_OBSCURED_P (f))
                 {
                   /* Don't allow freeing images and faces for this
                      frame as long as the frame's update wasn't
                      completed.  This prevents crashes when some Lisp
                      that runs from the various hooks or font-lock
                      decides to clear the frame's image cache and face
                      cache, when the images and faces in those caches
                      are referenced by the desired matrix.  */
                   f->inhibit_clear_image_cache = true;
->                redisplay_windows (FRAME_ROOT_WINDOW (f));
                 }

$ emacs-30.x --version
GNU Emacs 30.1
Development version 92e96a117525 on emacs-30 branch; build date 
2025-02-20.

What would you like me to do from here?

-Phil