Subject: Re: bug#42943: 28.0.50; Emacsclient crashes in ftcrfont_glyph_extents

From: Robert Pluim <[email-masked]>
Date: Sat, 24 Oct 2020 15:27:39 +0200

>>>>> On Sat, 24 Oct 2020 14:14:53 +0200, Robert Pluim <[email-masked]> said:

    Eli> I'm guessing that we close the font, but there's still a face that
    Eli> references that font, and we try using that face for display.  Can you
    Eli> see if that is the case?  The 'face' member of 'struct glyph_string'
    Eli> should point to the face, and face->font should point to the font.

    Robert> Yes, weʼre using the face thatʼs cached in the glyph_string:

    Robert> Thread 1 "emacs" received signal SIGSEGV, Segmentation fault.
    Robert> ftcrfont_glyph_extents (font=0x555556930478, glyph=1036,
    Robert>     metrics=metrics@entry=0x0) at ftcrfont.c:81
    Robert> 81        if (METRICS_STATUS (cache) == METRICS_INVALID)
    Robert> (gdb) up
    Robert> #1  0x00005555558453a1 in ftcrfont_draw (s=0x7fffffffb440,
    Robert>     from=<optimized out>, to=<optimized out>, x=17, y=<optimized out>,
    Robert>     with_background=<optimized out>) at ftcrfont.c:520
    Robert> 520           x += (s->padding_p ? 1 : ftcrfont_glyph_extents (s->font,
    Robert> (gdb) l 500
    Robert> 495       struct face *face = s->face;
    Robert> 496       struct font_info *ftcrfont_info = (struct font_info *) s->font;
    Robert> 497       cairo_t *cr;
    Robert> 498       cairo_glyph_t *glyphs;
    Robert> 499       int len = to - from;
    Robert> 500       int i;
    Robert> 501
    Robert> 502       block_input ();
    Robert> 503
    Robert> 504       cr = x_begin_cr_clip (f, s->gc);
    Robert> (gdb) p s->face
    Robert> $1 = (struct face *) 0x555556113290
    Robert> (gdb) p s->face->font
    Robert> $2 = (struct font *) 0x555556930478
    Robert> (gdb) p s->font
    Robert> $3 = (struct font *) 0x555556930478

And that font comes from here:

static int
fill_gstring_glyph_string (struct glyph_string *s, int face_id,
			   int start, int end, int overlaps)
{
  struct glyph *glyph, *last;
  Lisp_Object lgstring;
  int i;
  bool glyph_not_available_p;

  s->for_overlaps = overlaps;
  glyph = s->row->glyphs[s->area] + start;
  last = s->row->glyphs[s->area] + end;
  glyph_not_available_p = glyph->glyph_not_available_p;
  s->cmp_id = glyph->u.cmp.id;
  s->cmp_from = glyph->slice.cmp.from;
  s->cmp_to = glyph->slice.cmp.to + 1;
  s->face = FACE_FROM_ID (s->f, face_id);
  lgstring = composition_gstring_from_id (s->cmp_id);
  s->font = XFONT_OBJECT (LGSTRING_FONT (lgstring)); <----

so itʼs the caching in the Lisp_Object for the composition thatʼs
causing the problem.

I can also get it to crash by entering 'a' followed by U+306 (COMBINING
BREVE), but the initial code path is different, as then the
initial caching of the font is here:

Lisp_Object
hbfont_shape (Lisp_Object lgstring, Lisp_Object direction)
{
  struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));

(but the final crash is at the same place).

Robert
--