GNU bug report logs -
#71929
30.0.60; crash in mark_image_cache
Previous Next
Reported by: Sean Whitton <spwhitton <at> spwhitton.name>
Date: Thu, 4 Jul 2024 02:34:02 UTC
Severity: normal
Found in version 30.0.60
Done: Po Lu <luangruo <at> yahoo.com>
Bug is archived. No further changes may be made.
Full log
Message #98 received at 71929 <at> debbugs.gnu.org (full text, mbox):
Eli Zaretskii <eliz <at> gnu.org> writes:
> This is the initial frame of the daemon. It is not a GUI frame, and
> so it should not have a valid image cache. I guess some change is
> needed in verify_image_cache_refcount?
Not quite: init_frame_faces is apparently called before the frame is
entered into Vframe_list, so, likewise, the face cache's reference count
should be verified before it is incremented.
Sean, please retry with this patch substituted for the previous:
diff --git a/src/frame.c b/src/frame.c
index 7f4bf274ad9..9793b9f5cbe 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -4831,14 +4831,20 @@ gui_set_font (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
/* Clean F's image cache of images whose values are derived
from the font width. */
clear_image_cache (f, Qauto);
+ verify_image_cache_refcount (FRAME_IMAGE_CACHE (f));
}
else
{
+ struct image_cache *old_cache = FRAME_IMAGE_CACHE (f);
+
/* Release the current image cache, and reuse or allocate a
new image cache with IWIDTH. */
FRAME_IMAGE_CACHE (f)->refcount--;
+ FRAME_IMAGE_CACHE (f) = NULL;
+ verify_image_cache_refcount (old_cache);
FRAME_IMAGE_CACHE (f) = share_image_cache (f);
FRAME_IMAGE_CACHE (f)->refcount++;
+ verify_image_cache_refcount (FRAME_IMAGE_CACHE (f));
}
}
diff --git a/src/frame.h b/src/frame.h
index 1d920d1a6bc..8a636c56643 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -1682,6 +1682,31 @@ IMAGE_OPT_FROM_ID (struct frame *f, int id)
eassume (0 <= used);
return 0 <= id && id < used ? FRAME_IMAGE_CACHE (f)->images[id] : NULL;
}
+
+/* Abort if C is non-NULL and C's `refcount' field disagrees with the
+ number of frames holding references to the same. */
+
+INLINE void
+verify_image_cache_refcount (struct image_cache *c)
+{
+ int expected;
+ Lisp_Object tail, frame;
+
+ if (c)
+ {
+ expected = 0;
+
+ FOR_EACH_FRAME (tail, frame)
+ {
+ if (FRAME_IMAGE_CACHE (XFRAME (frame)) == c)
+ expected++;
+ }
+
+ if (expected != c->refcount)
+ emacs_abort ();
+ }
+}
+
#endif
/***********************************************************************
diff --git a/src/image.c b/src/image.c
index 2945447b962..9387c78408b 100644
--- a/src/image.c
+++ b/src/image.c
@@ -3625,6 +3625,7 @@ cache_image (struct frame *f, struct image *img)
{
c = FRAME_IMAGE_CACHE (f) = share_image_cache (f);
c->refcount++;
+ verify_image_cache_refcount (c);
}
/* Find a free slot in c->images. */
diff --git a/src/xfaces.c b/src/xfaces.c
index 188dd4778bc..ed4d404fbf3 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -678,7 +678,10 @@ init_frame_faces (struct frame *f)
/* Make or share an image cache. */
if (FRAME_WINDOW_P (f))
{
- FRAME_IMAGE_CACHE (f) = share_image_cache (f);
+ struct image_cache *c = share_image_cache (f);
+
+ verify_image_cache_refcount (c);
+ FRAME_IMAGE_CACHE (f) = c;
++FRAME_IMAGE_CACHE (f)->refcount;
}
#endif /* HAVE_WINDOW_SYSTEM */
@@ -709,6 +712,7 @@ free_frame_faces (struct frame *f)
struct image_cache *image_cache = FRAME_IMAGE_CACHE (f);
if (image_cache)
{
+ verify_image_cache_refcount (image_cache);
--image_cache->refcount;
if (image_cache->refcount == 0)
free_image_cache (f);
This bug report was last modified 301 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.