Commit 1431f667 authored by Eli Zaretskii's avatar Eli Zaretskii
Browse files

Avoid crashes when redisplayng a window changes faces or fonts

* src/xdisp.c (redisplay_internal): If redisplaying the selected
window or one of the frames turns on the frame's 'redisplay' flag,
redisplay again.  (Bug#21428)

* src/frame.c (x_set_font): Set the frame's 'fonts_changed' flag.
parent 57be62f9
......@@ -3651,6 +3651,10 @@ x_set_font (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
/* Attempt to hunt down bug#16028. */
SET_FRAME_GARBAGED (f);
/* This is important if we are called by some Lisp as part of
redisplaying the frame, see redisplay_internal. */
f->fonts_changed = true;
recompute_basic_faces (f);
do_pending_window_change (0);
......
......@@ -13810,6 +13810,7 @@ redisplay_internal (void)
bool gcscrollbars
/* Only GC scrollbars when we redisplay the whole frame. */
= f->redisplay || !REDISPLAY_SOME_P ();
bool f_redisplay_flag = f->redisplay;
/* Mark all the scroll bars to be removed; we'll redeem
the ones we want when we redisplay their windows. */
if (gcscrollbars && FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
......@@ -13853,6 +13854,20 @@ redisplay_internal (void)
goto retry_frame;
}
/* If the frame's redisplay flag was not set before
we went about redisplaying its windows, but it is
set now, that means we employed some redisplay
optimizations inside redisplay_windows, and
bypassed producing some screen lines. But if
f->redisplay is now set, it might mean the old
faces are no longer valid (e.g., if redisplaying
some window called some Lisp which defined a new
face or redefined an existing face), so trying to
use them in update_frame will segfault.
Therefore, we must redisplay this frame. */
if (!f_redisplay_flag && f->redisplay)
goto retry_frame;
/* Prevent various kinds of signals during display
update. stdio is not robust about handling
signals, which can cause an apparent I/O error. */
......@@ -13906,8 +13921,10 @@ redisplay_internal (void)
/* Compare desired and current matrices, perform output. */
update:
/* If fonts changed, display again. */
if (sf->fonts_changed)
/* If fonts changed, display again. Likewise if redisplay_window_1
above caused some change (e.g., a change in faces) that requires
considering the entire frame again. */
if (sf->fonts_changed || sf->redisplay)
goto retry;
/* Prevent freeing of realized faces, since desired matrices are
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment