Prevent segfaults due to frame resizing at the wrong time

* src/dispextern.h:
* src/xdisp.c (dont_resize_frames): New variable.
(unwind_format_mode_line): Decrement 'dont_resize_frames'.
(gui_consider_frame_title, display_mode_line, Fformat_mode_line):
Increment 'dont_resize_frames'.
* src/dispnew.c (do_pending_window_change): Don't resize frames if
'dont_resize_frames' is non-zero.  (Bug#81121)

(cherry picked from commit 94eb6389d4)
This commit is contained in:
Eli Zaretskii 2026-06-01 15:03:45 +03:00
parent 984932d4dc
commit f357a549ac
3 changed files with 21 additions and 3 deletions

View file

@ -3591,6 +3591,7 @@ int frame_mode_line_height (struct frame *);
extern bool redisplaying_p;
extern unsigned int redisplay_counter;
extern bool display_working_on_window_p;
extern int dont_resize_frames;
extern void unwind_display_working_on_window (void);
extern bool help_echo_showing_p;
extern Lisp_Object help_echo_string, help_echo_window;

View file

@ -6664,7 +6664,7 @@ deliver_window_change_signal (int sig)
void
do_pending_window_change (bool safe)
{
if (redisplaying_p && !safe)
if ((redisplaying_p || dont_resize_frames) && !safe)
return;
while (delayed_size_change)

View file

@ -1077,6 +1077,14 @@ bool redisplaying_p;
the callers. */
bool display_working_on_window_p;
/* Non-zero when we do not allow resizing frames. For example,
display_mode_line and other functions produce glyphs for the mode
line, in particular when called from non-redisplay code (so
redisplaying_p is false). We inhibit resizing of the frames during
that time, because that could change glyph_row pointers in the glyph
matrix behind the back of teh code which manipulates these pointers. */
int dont_resize_frames;
/* If a string, XTread_socket generates an event to display that string.
(The display is done in read_char.) */
@ -14015,6 +14023,9 @@ unwind_format_mode_line (Lisp_Object vector)
}
Vmode_line_unwind_vector = vector;
if (dont_resize_frames > 0)
dont_resize_frames--;
}
@ -14151,6 +14162,7 @@ gui_consider_frame_title (Lisp_Object frame)
title_start = MODE_LINE_NOPROP_LEN (0);
init_iterator (&it, XWINDOW (f->selected_window), -1, -1,
NULL, DEFAULT_FACE_ID);
dont_resize_frames++;
display_mode_element (&it, 0, -1, -1, fmt, Qnil, false);
len = MODE_LINE_NOPROP_LEN (title_start);
title = mode_line_noprop_buf + title_start;
@ -28138,6 +28150,10 @@ display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format)
format_mode_line_unwind_data (NULL, NULL,
Qnil, false));
/* We cannot allow frame-resizing as long as the code below runs,
because that could invalidate the it.glyph_row->glyphs pointers. */
dont_resize_frames++;
/* Temporarily make frame's keyboard the current kboard so that
kboard-local variables in the mode_line_format will get the right
values. */
@ -28253,8 +28269,6 @@ display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format)
}
pop_kboard ();
unbind_to (count, Qnil);
/* Fill up with spaces. */
display_string (" ", Qnil, Qnil, 0, 0, &it, 10000, -1, -1, 0);
@ -28284,6 +28298,8 @@ display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format)
- (it.current_x - it.last_visible_x)));
}
unbind_to (count, Qnil);
return it.glyph_row->height;
}
@ -29026,6 +29042,7 @@ are the selected window and the WINDOW's buffer). */)
set_buffer_internal_1 (XBUFFER (buffer));
init_iterator (&it, w, -1, -1, NULL, face_id);
dont_resize_frames++;
/* Make sure `base_line_number` is fresh in case we encounter a `%l`. */
if (current_buffer == XBUFFER ((w)->contents)