]> git.eshelyaron.com Git - emacs.git/commitdiff
Avoid segfaults due to image cache being cleared during redisplay
authorEli Zaretskii <eliz@gnu.org>
Mon, 4 Feb 2019 17:42:33 +0000 (19:42 +0200)
committerEli Zaretskii <eliz@gnu.org>
Mon, 4 Feb 2019 17:42:33 +0000 (19:42 +0200)
* 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.

src/frame.h
src/image.c
src/xdisp.c

index ab3efdfa926344017c2ba358342931b445181026..b7cbdd955717744c2b8dfa3c84fc45c3aeb2f13e 100644 (file)
@@ -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
index 57bbf3cdb9365c6f0ca84c6da69f65e14436aee8..642bf671520eea911978d6e9203954d41c6f1052 100644 (file)
@@ -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;
 
index b5034b513e6896ab486bf8fa4e9745c681b2b32f..0bffaeb60bcff4c27b695c3e9f31be9748e57675 100644 (file)
@@ -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