GNU bug report logs -
#60237
30.0.50; tree sitter core dumps when I edebug view a node
Previous Next
Reported by: Mickey Petersen <mickey <at> masteringemacs.org>
Date: Wed, 21 Dec 2022 12:30:02 UTC
Severity: normal
Found in version 30.0.50
Done: Stefan Monnier <monnier <at> iro.umontreal.ca>
Bug is archived. No further changes may be made.
Full log
Message #26 received at 60237 <at> debbugs.gnu.org (full text, mbox):
> From: Yuan Fu <casouri <at> gmail.com>
> Date: Fri, 24 Feb 2023 15:22:00 -0800
> Cc: eliz <at> gnu.org,
> 60237 <at> debbugs.gnu.org
>
> I’m stumbled on a reliably way to trigger a crash, of possibly the same cause as
> this one, by enabling the profiler and M-x garbage-collect in a
> tree-sitter mode on Mac. I tried to reproduce this on Linux but with no
> success.
>
> I was also able to trigger infinite loop by the same recipe on time, but I
> didn’t run that session under lldb. Anyway, we can focus on the crash
> first.
>
> Below’s the backtrace. Eli, could you see anything from this?
> [...]
> (lldb) down
> frame #0: 0x0000000100250f3d emacs`ASIZE(array=0x00000001a1889245) at lisp.h:1768:3
> 1765 ASIZE (Lisp_Object array)
> 1766 {
> 1767 ptrdiff_t size = XVECTOR (array)->header.size;
> -> 1768 eassume (0 <= size);
> 1769 return size;
> 1770 }
> 1771
> (lldb) p size
> (ptrdiff_t) $0 = -9223372036854775792
It looks like we are calling ASIZE in the context of GC, when the
vectors have their mark bit set, which makes ASIZE return negative
values: do
(gdb) p/x (unsigned long long)-9223372036854775792
$1 = 0x8000000000000010
So this is 16 (10 hex) with the array mark flag bit set. The fix is
simple:
diff --git a/src/eval.c b/src/eval.c
index 2dd0c35..7e6b742 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -4190,7 +4190,7 @@ mark_specpdl (union specbinding *first, union specbinding *ptr)
get_backtrace (Lisp_Object array)
{
union specbinding *pdl = backtrace_next (backtrace_top ());
- ptrdiff_t i = 0, asize = ASIZE (array);
+ ptrdiff_t i = 0, asize = gc_asize (array);
/* Copy the backtrace contents into working memory. */
for (; i < asize; i++)
> I suspect there is some stupid mistake that I made concerning gcing
> tree-sitter objects. Could you see anything suspicious from the
> following description:
>
> A Lisp_TS_Parser contains a TSParser and a TSTree, which are freed when
> the Lisp_TS_Parser is collected. A Lisp_TS_Node references the parser
> from which it is created, so that a Lisp_TS_Parser is only collected
> when no live node references it, because the Lisp_TS_Node references the
> TSTree stored in the Lisp_TS_Parser.
Sounds good, but do you understand why tree-sitter calls malloc when
you GC a parser? This is what we see in the backtrace:
> * frame #0: 0x0000000100250f3d emacs`ASIZE(array=0x00000001a1889245) at lisp.h:1768:3
> frame #1: 0x0000000100250e5e emacs`get_backtrace(array=0x00000001a1889245) at eval.c:4193:28
> frame #2: 0x00000001003001ce emacs`record_backtrace(log=0x00000001a1887d68, count=64) at profiler.c:162:3
> frame #3: 0x000000010030016d emacs`malloc_probe(size=64) at profiler.c:509:3
> frame #4: 0x0000000100204e6d emacs`xmalloc(size=64) at alloc.c:760:3
> frame #5: 0x0000000100e6c0c9 libtree-sitter.0.dylib`ts_subtree_release + 158
> frame #6: 0x0000000100e6f004 libtree-sitter.0.dylib`ts_tree_delete + 44
> frame #7: 0x0000000100307379 emacs`treesit_delete_parser(lisp_parser=0x00000001a2c0f0e0) at treesit.c:1182:3
As you see, when we call ts_tree_delete, it calls ts_subtree_release,
which in turn calls malloc (redirected into our xmalloc). Is this
expected? Can you look in the tree-sitter sources and verify that
this is OK?
This bug report was last modified 2 years and 128 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.