GNU bug report logs - #71929
30.0.60; crash in mark_image_cache

Previous Next

Package: emacs;

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 #50 received at 71929 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Po Lu <luangruo <at> yahoo.com>
Cc: 71929 <at> debbugs.gnu.org, spwhitton <at> spwhitton.name
Subject: Re: bug#71929: 30.0.60; crash in mark_image_cache
Date: Fri, 05 Jul 2024 10:37:23 +0300
> From: Po Lu <luangruo <at> yahoo.com>
> Cc: Sean Whitton <spwhitton <at> spwhitton.name>,  71929 <at> debbugs.gnu.org
> Date: Fri, 05 Jul 2024 14:41:31 +0800
> 
> Eli Zaretskii <eliz <at> gnu.org> writes:
> 
> >> From: Sean Whitton <spwhitton <at> spwhitton.name>
> >> Cc: 71929 <at> debbugs.gnu.org
> >> Date: Fri, 05 Jul 2024 08:13:14 +0800
> >> 
> >> Hello,
> >> 
> >> On Thu 04 Jul 2024 at 09:03am +03, Eli Zaretskii wrote:
> >> 
> >> >> What is the value of c->images?  IOW, why did this line segfault?
> >> >
> >> > Also, what is the value of c->refcount?
> >> 
> >> (gdb) p c
> >> $1 = (struct image_cache *) 0x555557c89e20
> >> (gdb) xpr
> >> There is no member named i.
> >> 
> >> (gdb) p c->images
> >> $2 = (struct image **) 0x35
> >> (gdb) xpr
> >> Cannot access memory at address 0x35
> >> 
> >> (gdb) p c->refcount
> >> $4 = 93823560581177
> >
> > So it's garbled.
> >
> > Po Lu, how do we handle the "shared" image cache when a frame is
> > deleted?  Where's the code which frees the cache if the cache's
> > refcount is one when the frame is deleted?
> 
> There's only one caller of free_image_cache, free_frame_faces, which is
> only called once in a frame's existence.  Cache refcounts are also
> altered from gui_set_font, but this process never entails decrementing a
> refcount to zero, as the caches under consideration are always retained
> by one or more frames:
> 
>   iwidth = max (10, FRAME_COLUMN_WIDTH (f));
>   if (FRAME_IMAGE_CACHE (f)
>       && (iwidth != FRAME_IMAGE_CACHE (f)->scaling_col_width))
>     {
>       eassert (FRAME_IMAGE_CACHE (f)->refcount >= 1);
>       if (FRAME_IMAGE_CACHE (f)->refcount == 1)
> 	{
> 	  /* This frame is the only user of this image cache.  */
> 	  FRAME_IMAGE_CACHE (f)->scaling_col_width = iwidth;
> 	  /* Clean F's image cache of images whose values are derived
> 	     from the font width.  */
> 	  clear_image_cache (f, Qauto);
> 	}
>       else
> 	{
> 	  /* Release the current image cache, and reuse or allocate a
> 	     new image cache with IWIDTH.  */
> 	  FRAME_IMAGE_CACHE (f)->refcount--;
> 	  FRAME_IMAGE_CACHE (f) = share_image_cache (f);
> 	  FRAME_IMAGE_CACHE (f)->refcount++;
> 	}
>     }

How does this answer my question?

The use case I was thinking of is that the image cache was shared,
then the last frame which shared the cache was deleted.  How do we
make sure the cache is freed and set to NULL in this situation?

IOW, we seem to have a cache that is not NULL but is also not a real
cache, as it cannot be accessed.  The question is how did that happen?




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.