aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2019-02-04 19:42:33 +0200
committerEli Zaretskii2019-02-04 19:42:33 +0200
commitef17247fe9cab2d59e470daad24314c868248b0a (patch)
treebdbc2082ba69afdfa637d7dbe44e9b9803b21a0d /src
parentf33a5dc9475ae43bb2477e648befd6a893d216f1 (diff)
downloademacs-ef17247fe9cab2d59e470daad24314c868248b0a.tar.gz
emacs-ef17247fe9cab2d59e470daad24314c868248b0a.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/frame.h4
-rw-r--r--src/image.c2
-rw-r--r--src/xdisp.c15
3 files changed, 19 insertions, 2 deletions
diff --git a/src/frame.h b/src/frame.h
index ab3efdfa926..b7cbdd95571 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -413,6 +413,10 @@ struct frame
413 /* Non-zero if this frame's faces need to be recomputed. */ 413 /* Non-zero if this frame's faces need to be recomputed. */
414 bool_bf face_change : 1; 414 bool_bf face_change : 1;
415 415
416 /* Non-zero if this frame's image cache cannot be freed because the
417 frame is in the process of being redisplayed. */
418 bool_bf inhibit_clear_image_cache : 1;
419
416 /* Bitfield area ends here. */ 420 /* Bitfield area ends here. */
417 421
418 /* This frame's change stamp, set the last time window change 422 /* This frame's change stamp, set the last time window change
diff --git a/src/image.c b/src/image.c
index 57bbf3cdb93..642bf671520 100644
--- a/src/image.c
+++ b/src/image.c
@@ -1554,7 +1554,7 @@ clear_image_cache (struct frame *f, Lisp_Object filter)
1554{ 1554{
1555 struct image_cache *c = FRAME_IMAGE_CACHE (f); 1555 struct image_cache *c = FRAME_IMAGE_CACHE (f);
1556 1556
1557 if (c) 1557 if (c && !f->inhibit_clear_image_cache)
1558 { 1558 {
1559 ptrdiff_t i, nfreed = 0; 1559 ptrdiff_t i, nfreed = 0;
1560 1560
diff --git a/src/xdisp.c b/src/xdisp.c
index b5034b513e6..0bffaeb60bc 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -14431,7 +14431,17 @@ redisplay_internal (void)
14431 FRAME_TERMINAL (f)->condemn_scroll_bars_hook (f); 14431 FRAME_TERMINAL (f)->condemn_scroll_bars_hook (f);
14432 14432
14433 if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f)) 14433 if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
14434 redisplay_windows (FRAME_ROOT_WINDOW (f)); 14434 {
14435
14436 /* Don't allow freeing images for this frame as long
14437 as the frame's update wasn't completed. This
14438 prevents crashes when some Lisp that runs from
14439 the various hooks or font-lock decides to clear
14440 the frame's image cache, when the images in that
14441 cache are referenced by the desired matrix. */
14442 f->inhibit_clear_image_cache = true;
14443 redisplay_windows (FRAME_ROOT_WINDOW (f));
14444 }
14435 /* Remember that the invisible frames need to be redisplayed next 14445 /* Remember that the invisible frames need to be redisplayed next
14436 time they're visible. */ 14446 time they're visible. */
14437 else if (!REDISPLAY_SOME_P ()) 14447 else if (!REDISPLAY_SOME_P ())
@@ -14512,6 +14522,7 @@ redisplay_internal (void)
14512 pending |= update_frame (f, false, false); 14522 pending |= update_frame (f, false, false);
14513 f->cursor_type_changed = false; 14523 f->cursor_type_changed = false;
14514 f->updated_p = true; 14524 f->updated_p = true;
14525 f->inhibit_clear_image_cache = false;
14515 } 14526 }
14516 } 14527 }
14517 } 14528 }
@@ -14539,6 +14550,7 @@ redisplay_internal (void)
14539 } 14550 }
14540 else if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf)) 14551 else if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
14541 { 14552 {
14553 sf->inhibit_clear_image_cache = true;
14542 displayed_buffer = XBUFFER (XWINDOW (selected_window)->contents); 14554 displayed_buffer = XBUFFER (XWINDOW (selected_window)->contents);
14543 /* Use list_of_error, not Qerror, so that 14555 /* Use list_of_error, not Qerror, so that
14544 we catch only errors and don't run the debugger. */ 14556 we catch only errors and don't run the debugger. */
@@ -14594,6 +14606,7 @@ redisplay_internal (void)
14594 XWINDOW (selected_window)->must_be_updated_p = true; 14606 XWINDOW (selected_window)->must_be_updated_p = true;
14595 pending = update_frame (sf, false, false); 14607 pending = update_frame (sf, false, false);
14596 sf->cursor_type_changed = false; 14608 sf->cursor_type_changed = false;
14609 sf->inhibit_clear_image_cache = false;
14597 } 14610 }
14598 14611
14599 /* We may have called echo_area_display at the top of this 14612 /* We may have called echo_area_display at the top of this