Subject: Re: bug#76091: 31.0.50; festure/igc: buffer.h:829: Emacs fatal error: assertion failed: BUFFERP (a)

From: Eli Zaretskii <[email-masked]>
Date: Fri, 07 Feb 2025 09:52:58 +0200

> From: Gregor Zattler <[email-masked]>
> Cc: [email-masked]
> Date: Fri, 07 Feb 2025 00:15:25 +0100
> 
> Hi Eli,
> * Gregor Zattler <[email-masked]> [2025-02-06; 16:48 +01]:
> > I'll try to use an un-optimized build
> > but I'm afraid it's too slow for
> > everyday usage.
> 
> So I did, it's really slow, but just
> usable, and I got a hit at the same
> breakpoint.  I again played around with
> org-noter.  When I finally hit C-x k (a
> convenience function which kills current
> buffer) the graphical frame vanished.
> It might even be that this is expected
> behaviour of org-noter but the daemon
> now hangs which it surely should not.

This is a different problem, see below.

> As always first infos for this
> build, then GDB output

Your GDB seems either misconfigured or buggy: it constantly complains
about exceptions in Python, like this:

  #12 0x000055555575ffef in eval_sub (form=Python Exception <class 'gdb.error'>: value has been optimized out
  , form@entry=XIL(0x7fffbb79996b)) at ./src/eval.c:2560

Please either upgrade or downgrade your GDB, or figure out what is the
problem in the configuration (incompatible Python version, perhaps?) and
fix it.  It gets in the way of reading the backtraces.

> +run --debug-init -xrm --init-directory="${USER_EMACS_DIRECTORY}" --fg-daemon="${EMACS_SERVER_NAME}"

These "+" signs are due to "set trace-command on" setting you use,
which is fine for commands you type, but it also expands all the
user-defined commands we have in src/.gdbinit, and that makes the
results very hard to read, because the results are buried in gobs of
unhelpful command lines.  Example:

> ++set $bt = backtrace_top ()
> ++if backtrace_p ($bt)
> +++echo \n
> 
> +++echo Lisp Backtrace:\n
> Lisp Backtrace:
> +++xbacktrace
> ++++set $bt = backtrace_top ()
> ++++while backtrace_p ($bt)
> +++++set $fun = backtrace_function ($bt)
> +++++xgettype $fun
> ++++++if (CHECK_LISP_OBJECT_TYPE)
> +++++++set $bugfix = $fun.i
> ++++++set $type = (enum Lisp_Type) (USE_LSB_TAG ? (EMACS_INT) $bugfix & (1 << GCTYPEBITS) - 1 : (EMACS_UINT) $bugfix >> VALBITS)
> +++++if $type == Lisp_Symbol
> ++++++xprintsym $fun
> +++++++xsymname $fun
> ++++++++xgetsym $fun
> +++++++++xgetptr $fun
> ++++++++++if (CHECK_LISP_OBJECT_TYPE)
> +++++++++++set $bugfix = $fun.i
> ++++++++++set $ptr = (EMACS_INT) $bugfix & VALMASK
> +++++++++set $ptr = ((struct Lisp_Symbol *) ((char *) &lispsym + $ptr))
> ++++++++set $symname = $ptr->u.s.name
> +++++++xgetptr $symname
> ++++++++if (CHECK_LISP_OBJECT_TYPE)
> +++++++++set $bugfix = $symname.i
> ++++++++set $ptr = (EMACS_INT) $bugfix & VALMASK
> +++++++if $ptr != 0
> ++++++++set $sym_name = (struct Lisp_String *) $ptr
> ++++++++xprintstr $sym_name
> +++++++++if (! $arg0)
> ++++++++++set $data = (char *) $sym_name->u.s.data
> ++++++++++set $strsize = ($sym_name->u.s.size_byte < 0) ? ($sym_name->u.s.size & ~ARRAY_MARK_FLAG) : $sym_name->u.s.size_byte
> ++++++++++if $strsize == 0
> +++++++++++output ($sym_name->u.s.size > 1000) ? 0 : ($data[0])@($strsize)
> "delete-frame"++++++printf " (0x%x)\n", backtrace_args ($bt)
>  (0xffffaf10)

This should have been just the following 2 lines:

  Lisp backtrace:
  "delete-frame" (0xffffaf10)

So please don't use "set trace-command on" in the future, when
reporting results of GDB sessions here.

> Breakpoint 1, terminate_due_to_signal (sig=sig@entry=6, backtrace_limit=backtrace_limit@entry=2147483647) at ./src/emacs.c:425
> 425	{
> +t
> [Current thread is 1 (Thread 0x7ffff4f48000 (LWP 1750449))]
> +bt
> #0  terminate_due_to_signal (sig=sig@entry=6, backtrace_limit=backtrace_limit@entry=2147483647) at ./src/emacs.c:425
> #1  0x00005555557d9a62 in set_state (state=state@entry=IGC_STATE_DEAD) at ./src/igc.c:1017
> #2  0x00005555557d9a96 in igc_assert_fail (file=file@entry=0x555555903e97 "igc.c", line=line@entry=3020, msg=msg@entry=0x5555558f2277 "r == NULL") at ./src/igc.c:306
> #3  0x00005555557da4e4 in igc_check_freeable (start=start@entry=0x555555b2b8f0) at ./src/igc.c:3020
> #4  0x0000555555736d12 in xfree (block=block@entry=0x555555b2b8f0) at ./src/alloc.c:760
> #5  0x00005555556889f0 in x_delete_display (dpyinfo=dpyinfo@entry=0x555555b2b8f0) at ./src/xterm.c:31925
> #6  0x000055555569385e in x_delete_terminal (terminal=0x7fffd549a0c0) at ./src/xterm.c:32154
> #7  0x000055555567099a in Fdelete_terminal (terminal=terminal@entry=XIL(0x7fffd549a0c5), force=XIL(0x38)) at ./src/terminal.c:428

This seems to be a bug in x_delete_display: while dpyinfo is allocated
in x_term_init by igc_xzalloc, it is freed by xfree:

  struct x_display_info *
  x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
  {
    [...]
  #ifdef HAVE_MPS
    // FIXME/igc: use exact references
    dpyinfo = igc_xzalloc_ambig (sizeof *dpyinfo);
  #else
    dpyinfo = xzalloc (sizeof *dpyinfo);
  #endif

but

  static void
  x_delete_display (struct x_display_info *dpyinfo)
  {
    [...]
    xfree (dpyinfo);
  }