mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-16 09:14:18 +00:00
Avoid segfaults due to image cache being cleared during redisplay
* src/xdisp.c (redisplay_internal): Set the inhibit_clear_image_cache flag of a frame while its windows are being redisplayed, and reset the flag after the call top update_frame returns. * src/image.c (clear_image_cache): Do nothing if the frame's inhibit_clear_image_cache flag is set. (Bug#34256) * src/frame.h (struct frame): New flag inhibit_clear_image_cache.
This commit is contained in:
parent
f33a5dc947
commit
ef17247fe9
3 changed files with 19 additions and 2 deletions
|
|
@ -413,6 +413,10 @@ struct frame
|
|||
/* Non-zero if this frame's faces need to be recomputed. */
|
||||
bool_bf face_change : 1;
|
||||
|
||||
/* Non-zero if this frame's image cache cannot be freed because the
|
||||
frame is in the process of being redisplayed. */
|
||||
bool_bf inhibit_clear_image_cache : 1;
|
||||
|
||||
/* Bitfield area ends here. */
|
||||
|
||||
/* This frame's change stamp, set the last time window change
|
||||
|
|
|
|||
|
|
@ -1554,7 +1554,7 @@ clear_image_cache (struct frame *f, Lisp_Object filter)
|
|||
{
|
||||
struct image_cache *c = FRAME_IMAGE_CACHE (f);
|
||||
|
||||
if (c)
|
||||
if (c && !f->inhibit_clear_image_cache)
|
||||
{
|
||||
ptrdiff_t i, nfreed = 0;
|
||||
|
||||
|
|
|
|||
15
src/xdisp.c
15
src/xdisp.c
|
|
@ -14431,7 +14431,17 @@ redisplay_internal (void)
|
|||
FRAME_TERMINAL (f)->condemn_scroll_bars_hook (f);
|
||||
|
||||
if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
|
||||
redisplay_windows (FRAME_ROOT_WINDOW (f));
|
||||
{
|
||||
|
||||
/* Don't allow freeing images 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, when the images in that
|
||||
cache are referenced by the desired matrix. */
|
||||
f->inhibit_clear_image_cache = true;
|
||||
redisplay_windows (FRAME_ROOT_WINDOW (f));
|
||||
}
|
||||
/* Remember that the invisible frames need to be redisplayed next
|
||||
time they're visible. */
|
||||
else if (!REDISPLAY_SOME_P ())
|
||||
|
|
@ -14512,6 +14522,7 @@ redisplay_internal (void)
|
|||
pending |= update_frame (f, false, false);
|
||||
f->cursor_type_changed = false;
|
||||
f->updated_p = true;
|
||||
f->inhibit_clear_image_cache = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14539,6 +14550,7 @@ redisplay_internal (void)
|
|||
}
|
||||
else if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
|
||||
{
|
||||
sf->inhibit_clear_image_cache = true;
|
||||
displayed_buffer = XBUFFER (XWINDOW (selected_window)->contents);
|
||||
/* Use list_of_error, not Qerror, so that
|
||||
we catch only errors and don't run the debugger. */
|
||||
|
|
@ -14594,6 +14606,7 @@ redisplay_internal (void)
|
|||
XWINDOW (selected_window)->must_be_updated_p = true;
|
||||
pending = update_frame (sf, false, false);
|
||||
sf->cursor_type_changed = false;
|
||||
sf->inhibit_clear_image_cache = false;
|
||||
}
|
||||
|
||||
/* We may have called echo_area_display at the top of this
|
||||
|
|
|
|||
Loading…
Reference in a new issue