Subject: Re: bug#72692: Emacs 31.05 (40eecd594ac) get SIGSEGV on Linux (Linux 6.6.45 Kde Wayland)

From: Pip Cet <[email-masked]>
Date: Sun, 18 Aug 2024 12:43:06 +0000

<[email-masked]> writes:

> It's
> ```
> Redefine command "xbacktrace"? (y or n) [answered Y; input not from terminal]
> Redefine command "xprintbytestr"? (y or n) [answered Y; input not from terminal]
> Redefine command "xwhichsymbols"? (y or n) [answered Y; input not from terminal]
> Redefine command "hookpost-backtrace"? (y or n) [answered Y; input not from terminal]
> Redefine command "ff"? (y or n) [answered Y; input not from terminal]
> DISPLAY = :0
> TERM = tmux-256color
> Breakpoint 3 at 0x4736d9: file emacs.c, line 431.
> Breakpoint 4 at 0x562640: file xterm.c, line 27093.
> (gdb) frame 9
> #9  0x00000000006dd64d in fontset_font (fontset=fontset@entry=XIL(0), c=c@entry=127802, face=face@entry=0x13fec610, id=-1) at fontset.c:793
> 793       rfont_def = fontset_find_font (fontset, c, face, id, 0);
> (gdb) p *face->ascii_face
> $1 = {
>   lface = {XIL(0x8220), XIL(0x28bdef4), XIL(0x28bdf34), XIL(0xe340), make_fixnum(90), XIL(0xe340), XIL(0xe340), XIL(0), XIL(0), XIL(0x4417994), XIL(0x233c9c4), XIL(0), XIL(0), XIL(0), XIL(0x7f9ea6b05d63),
>     XIL(0x765a8285), XIL(0), XIL(0x2aabee4), XIL(0x13500), XIL(0)},
>   id = 2,
>   gc = 0x0,
>   stipple = 0,
>   foreground = 4288059542,
>   background = 4278190080,
>   underline_color = 0,
>   overline_color = 0,
>   strike_through_color = 0,
>   box_color = 4281545523,
>   font = 0x1e4370d0,
>   fontset = 5,
>   box_vertical_line_width = -1,
>   box_horizontal_line_width = -1,
>   underline_pixels_above_descent_line = 0,
>   box = FACE_SIMPLE_BOX,
>   underline = FACE_NO_UNDERLINE,
>   use_box_color_for_shadows_p = true,
>   overline_p = false,
>   strike_through_p = false,
>   foreground_defaulted_p = false,
>   background_defaulted_p = false,
>   underline_defaulted_p = false,
>   overline_color_defaulted_p = false,
>   strike_through_color_defaulted_p = false,
>   box_color_defaulted_p = true,
>   underline_at_descent_line_p = false,
>   tty_bold_p = false,
>   tty_italic_p = false,
>   tty_reverse_p = false,
>   tty_strike_through_p = false,
>   colors_copied_bitwise_p = false,
>   overstrike = false,
>   hash = 322003229,
>   next = 0x13fec610,
>   prev = 0x0,
>   ascii_face = 0x4d7343a0,
>   extra = 0x0
> }
> (gdb)
> ```

Thanks. That has a different fontset, so it looks like a fontset was
prematurely freed while still being referred to by a face.  I think the
assumption made in xfaces.c, that it's always safe to free a fontset if
we're freeing the realized ASCII face, is incorrect.

I can confirm that we're sometimes leaving a frame's fontset field
invalid by running this code:

diff --git a/src/xfaces.c b/src/xfaces.c
index 684b6ccfac7..34bab822022 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -4598,7 +4598,23 @@ free_realized_face (struct frame *f, struct face *face)
 	{
 	  /* Free fontset of FACE if it is ASCII face.  */
 	  if (face->fontset >= 0 && face == face->ascii_face)
-	    free_face_fontset (f, face);
+	    {
+	      struct face_cache *cache = FRAME_FACE_CACHE (f);
+	      if (cache)
+		{
+		  for (int i = 0; i < cache->used; i++)
+		    {
+		      struct face *face2 = cache->faces_by_id[i];
+		      if (face2 != 0 && face2 != face && face2->fontset == face->fontset)
+			{
+			  message ("Freeing fontset %d that's still in use!", face->fontset);
+			  goto dont;
+			}
+		    }
+		}
+	      free_face_fontset (f, face);
+	    }
+	dont:
 
 #ifdef HAVE_X_WINDOWS
 	  /* This function might be called with the frame's display

However, that's not a fix; it would leak fontsets, and it's slow.

Will investigate further.

Thanks
Pip