Subject: Re: bug#75477: 31.0.50; scratch/igc: crash on the latest commit

From: Pip Cet <[email-masked]>
Date: Fri, 10 Jan 2025 14:27:55 +0000

"Ihor Radchenko" <[email-masked]> writes:

> While waiting to see if bug#75292 has been fixed on the latest
> scratch/igc. Is experiences Emacs hanging and even crashing when
> creating a new frame.

Thanks for the report!  Think I found it.

> I have managed to capture a backtrace today:
>
> Thread 1 "emacs" hit Breakpoint 1, terminate_due_to_signal (sig=sig@entry=11, backtrace_limit=backtrace_limit@entry=40) at emacs.c:432
> 432	{
> (gdb) bt
> #0  terminate_due_to_signal (sig=sig@entry=11, backtrace_limit=backtrace_limit@entry=40) at emacs.c:432
> #1  0x00005555556efeb5 in handle_fatal_signal (sig=sig@entry=11) at sysdep.c:1799
> #2  0x00005555556eff22 in deliver_thread_signal (sig=11, handler=0x5555556efea3 <handle_fatal_signal>) at sysdep.c:1791
> #3  deliver_fatal_thread_signal (sig=sig@entry=11) at sysdep.c:1811
> #4  0x00005555556eff52 in handle_sigsegv (sig=11, siginfo=<optimized out>, arg=<optimized out>) at sysdep.c:1949
> #5  0x00007ffff2c41100 in <signal handler called> () at /lib64/libc.so.6
> #6  0x00007ffff2c412db in kill () at /lib64/libc.so.6
> #7  0x0000555555893629 in sigHandle (sig=<optimized out>, info=<optimized out>, uap=<optimized out>) at /home/yantar92/Dist/mps/code/protsgix.c:114
> #8  0x00007ffff2c41100 in <signal handler called> () at /lib64/libc.so.6
> #9  scan_ambig (ss=0x7fffffffa6c8, start=<optimized out>, end=0x555596d238f0, closure=<optimized out>) at igc.c:1552

We were asked to scan memory ending at 0x555596d238f0 (the start address
was optimized out), which we had registered as an ambiguous root, but
the scan function segfaulted; most likely, the memory we scanned was not
mapped (or no longer mapped).

My first suspect was the framep area we allocate for the X widget, but
that's an 8-byte area allocated with malloc: therefore, it's 16-byte
aligned, so the end address would have to end in 8 rather than 0.

The GTK code creates a lot of temporary roots, most of them by using
igc_xzalloc_ambig (8): again, it's very unlikely one of those is our
culprit because of the aligned end pointer.

So it must be a different object.  So far, what I've found was:

void
xg_free_frame_widgets (struct frame *f)
{
  if (FRAME_GTK_OUTER_WIDGET (f))
    {
      xp_output *x = f->output_data.xp;
      struct xg_frame_tb_info *tbinfo
        = g_object_get_data (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)),
                             TB_INFO_KEY);
      if (tbinfo)
        xfree (tbinfo);

which calls xfree() on a pointer that was obtained with igc_xzalloc.
Definitely a bug, usually a harmless one, except in the very rare case
that xfree unmaps memory rather than merely putting it on the free list.

That would match the alignment, and it would explain the bug if we hit
one of the (very rare; almost impossible if malloc uses sbrk, unlikely
if malloc uses mmap) cases in which xfree actually unmaps memory rather
than merely putting the block on the free list.

But this function is called during frame deletion, not frame creation.
Did you delete any frames in this session?

Pip