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

From: "Basil L. Contovounesios" <[email-masked]>
Date: Tue, 14 Sep 2021 00:21:17 +0100

Eli Zaretskii [2021-09-13 19:03 +0300] wrote:

>> #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).

For some reason, if I set a watch- or break-point with a condition that
involves untagging a structure, e.g. XFRAME or XSTRING, GDB gives me
something like the following:

  Error in testing breakpoint condition:                                                                                            
  Couldn't get registers: No such process.                                                                                          
  An error occurred while in a function called from GDB.                                                                            
  Evaluation of the expression containing the function                                                                              
  (SDATA) will be abandoned.                                                                                                        
  When the function is done executing, GDB will silently stop.                                                                      
  Selected thread is running.

Where SDATA may also be XFRAME/XSTRING depending on the condition.  Not
sure what that's about.

In any case, I was able to manually continue execution until
init_iterator was dealing with the desired frame.  If you know of a way
to streamline this, please let me know.

Note that, at the time that I issue 'bt full' in the attached log, the
single visible *scratch* frame has the following in the echo area:

  Error during bug-reference-auto-setup: (no-catch sucess t)

So there's an uncaught signal (presumably due to a typo) in the mix too.

Thanks,

-- 
Basil