Subject: Re: bug#50571: 28.0.50; Redisplay segfaults with empty face cache

From: Eli Zaretskii <[email-masked]>
Date: Mon, 13 Sep 2021 19:03:21 +0300

> Date: Mon, 13 Sep 2021 15:59:29 +0100
> From:  "Basil L. Contovounesios" via "Bug reports for GNU Emacs,
>  the Swiss army knife of text editors" <[email-masked]>
> 
> I can reliably cause Emacs to segfault with my current config and
> installed packages with the following steps specific to my system:
> 
> 0. C-x p p (project-switch-project)
> 1. Select a checkout of https://github.com/kyleam/bog,
>    using Ivy completion.
> 2. m (magit-project-status)

Thanks.  I'd prefer not to install two huge packages, so would you
please help me understand better what's going on in this recipe?

Here's what puzzles me:

> #0  terminate_due_to_signal (sig=6, backtrace_limit=2147483647) at emacs.c:400
> #1  0x00005555557d4f5f in die
>     (msg=0x55555592d2e8 "0 <= id && id < FRAME_FACE_CACHE (f)->used", file=0x55555592d2da "frame.h", line=1433) at alloc.c:7479
> #2  0x00005555556c89f1 in FACE_FROM_ID (f=0x5555562070b0, id=0) at frame.h:1433
> #3  0x00005555556d9e57 in face_at_buffer_position
>     (w=0x555556207318, pos=1, endptr=0x7fffffff7f70, limit=101, mouse=false, base_face_id=0, attr_filter=0) at xfaces.c:6425
> #4  0x00005555555d41d0 in face_at_pos (it=0x7fffffff8170, attr_filter=0) at xdisp.c:4379
> #5  0x00005555555d44cd in handle_face_prop (it=0x7fffffff8170) at xdisp.c:4480
> #6  0x00005555555d2977 in handle_stop (it=0x7fffffff8170) at xdisp.c:3854
> #7  0x00005555555dd96a in reseat (it=0x7fffffff8170, pos=..., force_p=true) at xdisp.c:7112
> #8  0x00005555555d1abb in init_iterator
>     (it=0x7fffffff8170, w=0x555556207318, charpos=1, bytepos=1, row=0x555557419f80, base_face_id=DEFAULT_FACE_ID) at xdisp.c:3455

init_iterator makes sure the frame's face cache includes all the basic
faces, around line 3220 of xdisp.c:

  /* If realized faces have been removed, e.g. because of face
     attribute changes of named faces, recompute them.  When running
     in batch mode, the face cache of the initial frame is null.  If
     we happen to get called, make a dummy face cache.  */
  if (FRAME_FACE_CACHE (it->f) == NULL)
    init_frame_faces (it->f);
  if (FRAME_FACE_CACHE (it->f)->used == 0)
    recompute_basic_faces (it->f);

The backtrace you sent starts at line 3455 of xdisp.c.  So somewhere
between these two places, or maybe inside reseat and the functions it
calls, the frame's face cache gets cleared.  Can you please put a
watchpoint on it->f->face_cache->used, after the above snippet makes
sure the cache is valid and the basic faces are cached in it, and see
where the cache gets cleared?  Be sure to use the -l (ell) switch of
the "watch" command in GDB, so it's valid even when you are not in the
lexical scope of init_iterator.

When the watchpoint breaks, please show both the C backtrace and the
Lisp backtrace (using the "xbacktrace" command if needed).

I hope this will tell us enough to understand whodunit.

Thanks.