Subject: Re: bug#71929: 30.0.60; crash in mark_image_cache

From: Po Lu <[email-masked]>
Date: Fri, 05 Jul 2024 14:41:31 +0800

Eli Zaretskii <[email-masked]> writes:

>> From: Sean Whitton <[email-masked]>
>> Cc: [email-masked]
>> 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++;
	}
    }