clojure-emacs / clojure-ts-mode

The next generation Clojure major mode for Emacs, powered by TreeSitter
GNU General Public License v3.0
140 stars 13 forks source link

My Clojure TS mode often freezes #51

Closed vinurs closed 2 months ago

vinurs commented 2 months ago

i use emacs-plus , and compile using the follow

HOMEBREW_EMACS_PLUS_30_REVISION=89c99891b2b3ab087cd7e824cef391ef26800ab4 brew install emacs-plus@30 --with-dbus --with-debug --with-mailutils --with-elrumo2-icon --with-imagemagick --with-xwidgets --with-poll

my system is macos 15.0 this is my minimal cfg file

(add-to-list 'treesit-extra-load-path (expand-file-name "tree-sitter/" user-emacs-directory))
(add-to-list 'load-path "~/.emacs.d/site-lisp/clojure-ts-mode")
(require 'clojure-ts-mode)

;; debug
(setq debug-on-quit t)

i cloned clojure ts mode in .emacs.d/site-lisp/ then open emacs , open the the attachment file. elong.clj , go to line 57, then input

(comment

then the emacs It seems like Emacs has frozen, and the CPU usage is at 100%.

lldb -p $(ps aux | grep '[E]macs' | awk '{print $2}')
(lldb) process attach --pid 16819
Process 16819 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
    frame #0: 0x0000000198080810 libsystem_malloc.dylib`nanov2_allocate_outlined + 376
libsystem_malloc.dylib`nanov2_allocate_outlined:
->  0x198080810 <+376>: str    xzr, [x23]
    0x198080814 <+380>: str    xzr, [x23, #0x8]
    0x198080818 <+384>: b      0x198080838    ; <+416>
    0x19808081c <+388>: tbz    w21, #0x0, 0x198080834 ; <+412>
Executable module set to "/opt/homebrew/Cellar/emacs-plus@30/30.0.60/Emacs.app/Contents/MacOS/Emacs".
Architecture set to: arm64-apple-macosx-.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
  * frame #0: 0x0000000198080810 libsystem_malloc.dylib`nanov2_allocate_outlined + 376
    frame #1: 0x000000019807ef98 libsystem_malloc.dylib`nanov2_malloc_type + 472
    frame #2: 0x0000000104cca590 Emacs`xmalloc + 20
    frame #3: 0x00000001057e1cd0 libtree-sitter.0.23.dylib`stack__iter + 116
    frame #4: 0x00000001057e890c libtree-sitter.0.23.dylib`ts_parser__reduce + 92
    frame #5: 0x00000001057d96e8 libtree-sitter.0.23.dylib`ts_parser_parse + 5204
    frame #6: 0x0000000104d784c8 Emacs`Ftreesit_parser_root_node + 236
    frame #7: 0x0000000104cf9ad4 Emacs`funcall_subr + 288
    frame #8: 0x0000000104cf4378 Emacs`Ffuncall + 412
    frame #9: 0x0000000104d06cc8 Emacs`mapcar1 + 652
    frame #10: 0x0000000104d06e18 Emacs`Fmapcar + 220
    frame #11: 0x0000000104cf9a1c Emacs`funcall_subr + 104
    frame #12: 0x0000000104d409fc Emacs`exec_byte_code + 2180
    frame #13: 0x0000000104cf4378 Emacs`Ffuncall + 412
    frame #14: 0x0000000104cf9364 Emacs`Frun_hook_wrapped + 224
    frame #15: 0x0000000104cf9a1c Emacs`funcall_subr + 104
    frame #16: 0x0000000104d409fc Emacs`
[elong.txt](https://github.com/user-attachments/files/16965551/elong.txt)
exec_byte_code + 2180
    frame #17: 0x0000000104cf4378 Emacs`Ffuncall + 412
    frame #18: 0x0000000104cf6dcc Emacs`internal_condition_case_n + 120
    frame #19: 0x0000000104bb82e0 Emacs`dsafe_call1 + 160
    frame #20: 0x0000000104bbf4f0 Emacs`handle_fontified_prop + 716
    frame #21: 0x0000000104bbdc58 Emacs`handle_stop + 112
    frame #22: 0x0000000104bbca34 Emacs`next_element_from_buffer + 248
    frame #23: 0x0000000104baf374 Emacs`get_next_display_element + 140
    frame #24: 0x0000000104bd06a4 Emacs`display_line + 1120
    frame #25: 0x0000000104bd9b58 Emacs`redisplay_window + 13536
    frame #26: 0x0000000104bd4468 Emacs`redisplay_window_1 + 44
    frame #27: 0x0000000104cf6c90 Emacs`internal_condition_case_1 + 100
    frame #28: 0x0000000104bcd8b0 Emacs`redisplay_internal + 4216
    frame #29: 0x0000000104c6f0c4 Emacs`read_char + 3212
    frame #30: 0x0000000104c6c1e8 Emacs`read_key_sequence + 1388
    frame #31: 0x0000000104c6aa38 Emacs`command_loop_1 + 864
    frame #32: 0x0000000104cf6c04 Emacs`internal_condition_case + 96
    frame #33: 0x0000000104c69c50 Emacs`command_loop_2 + 52
    frame #34: 0x0000000104cf632c Emacs`internal_catch + 88
    frame #35: 0x0000000104dd80a0 Emacs`command_loop.cold.1 + 88
    frame #36: 0x0000000104c69c1c Emacs`command_loop + 156
    frame #37: 0x0000000104c69acc Emacs`recursive_edit_1 + 168
    frame #38: 0x0000000104c6a1b0 Emacs`Frecursive_edit + 388
    frame #39: 0x0000000104c68c00 Emacs`main + 8416
    frame #40: 0x0000000197ed0274 dyld`start + 2840
(lldb)
vinurs commented 2 months ago

elong.txt rename elong.txt to elong.clj

vinurs commented 2 months ago

https://github.com/user-attachments/assets/7ce5803f-f2c9-4094-941c-8ed642d7f848

I recorded a screen capture

sogaiu commented 2 months ago

FWIW, it doesn't happen for me using Emacs 29.3 on Void Linux with:

vinurs commented 2 months ago

@sogaiu just now , i compile emacs 29, then it works ok brew install emacs-plus@29 --with-dbus --with-debug --with-mailutils --with-elrumo2-icon --with-imagemagick --with-xwidgets --with-poll but both emacs-30 and emacs-31 i've tried , the same problem

vinurs commented 2 months ago

I'm not sure if it's related to the Chinese characters in my code, but this issue occurs very frequently. Once it happens, it’s almost certain to recur, and I have to forcefully kill Emacs. However, the same issue will reoccur in the same place. I have to use another editor to make slight modifications before continuing to edit in Emacs.

sogaiu commented 2 months ago

If you strip out all of the Chinese characters from elong.clj, does it happen?

Not sure if I managed to remove them all, but perhaps I got close:

elong-stripped.txt

vinurs commented 2 months ago

After removing all the Chinese characters, I still don't have a surefire way to reproduce the issue, the file u attached is ok now

sogaiu commented 2 months ago

Looking at:

  * frame #0: 0x0000000198080810 libsystem_malloc.dylib`nanov2_allocate_outlined + 376
    frame #1: 0x000000019807ef98 libsystem_malloc.dylib`nanov2_malloc_type + 472
    frame #2: 0x0000000104cca590 Emacs`xmalloc + 20
    frame #3: 0x00000001057e1cd0 libtree-sitter.0.23.dylib`stack__iter + 116

That looks somewhat related to memory allocation perhaps.

FWIW, there is a stack__iter in tree-sitter around here. Not sure if this particular version of the file matches what was used.

sogaiu commented 2 months ago

I kind of doubt that this is an issue with clojure-ts-mode or tree-sitter-clojure (some tree-sitter grammars have a hand-crafted C file, but tree-sitter-clojure doesn't).

If I had to guess, I'd imagine it might have to do with Emacs, tree-sitter, or possibly Emacs Plus if that applies any patches.

I found this issue at the Emacs Plus repository about a crash. It seems that the maintainter then suggested:

Can you please try to reproduce with https://emacsformacosx.com/builds. If it's reproducible with 'bare' Emacs -> it needs to be reported to Emacs bug tracker.

vinurs commented 2 months ago

CleanShot 2024-09-12 at 00 10 24@2x i choose a version from https://emacsformacosx.com/builds , then open the file,This issue can be reproduced

lldb -p $(ps aux | grep '[E]macs' | awk '{print $2}')

(lldb) process attach --pid 24314
Process 24314 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
    frame #0: 0x000000019805c850 libsystem_malloc.dylib`nanov2_find_block_and_allocate + 368
libsystem_malloc.dylib`nanov2_find_block_and_allocate:
->  0x19805c850 <+368>: ldrsw  x16, [x17, x16, lsl #2]
    0x19805c854 <+372>: adr    x17, 0x19805c854 ; <+372>
    0x19805c858 <+376>: add    x16, x17, x16
    0x19805c85c <+380>: br     x16
Executable module set to "/Applications/Emacs.app/Contents/MacOS/Emacs-arm64-11".
Architecture set to: arm64-apple-macosx-.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
  * frame #0: 0x000000019805c850 libsystem_malloc.dylib`nanov2_find_block_and_allocate + 368
    frame #1: 0x0000000198080798 libsystem_malloc.dylib`nanov2_allocate_outlined + 256
    frame #2: 0x000000019807fa70 libsystem_malloc.dylib`nanov2_malloc_type_zero_on_alloc + 488
    frame #3: 0x0000000104e937c4 Emacs-arm64-11`lmalloc + 44
    frame #4: 0x0000000104e93760 Emacs-arm64-11`xmalloc + 24
    frame #5: 0x0000000105945684 libtree-sitter.0.dylib`ts_stack_pop_count + 140
    frame #6: 0x0000000105938aec libtree-sitter.0.dylib`ts_parser__reduce + 108
    frame #7: 0x00000001059370d8 libtree-sitter.0.dylib`ts_parser_parse + 5796
    frame #8: 0x0000000104f2fec8 Emacs-arm64-11`treesit_ensure_parsed + 112
    frame #9: 0x0000000104f2fe00 Emacs-arm64-11`Ftreesit_parser_root_node + 52
    frame #10: 0x0000000104ebf25c Emacs-arm64-11`funcall_subr + 344
    frame #11: 0x0000000104ebf0d0 Emacs-arm64-11`funcall_general + 336
    frame #12: 0x0000000104ebb2a4 Emacs-arm64-11`Ffuncall + 176
    frame #13: 0x0000000104ecacfc Emacs-arm64-11`mapcar1 + 216
    frame #14: 0x0000000104ecaec8 Emacs-arm64-11`Fmapcar + 168
    frame #15: 0x0000000104ebf16c Emacs-arm64-11`funcall_subr + 104
    frame #16: 0x0000000104efb554 Emacs-arm64-11`exec_byte_code + 2264
    frame #17: 0x0000000104ebf4e4 Emacs-arm64-11`funcall_lambda + 464
    frame #18: 0x0000000104ebf0b8 Emacs-arm64-11`funcall_general + 312
    frame #19: 0x0000000104ebb2a4 Emacs-arm64-11`Ffuncall + 176
    frame #20: 0x0000000104ebedd4 Emacs-arm64-11`run_hook_wrapped_funcall + 28
    frame #21: 0x0000000104ebec30 Emacs-arm64-11`run_hook_with_args + 236
    frame #22: 0x0000000104ebedb0 Emacs-arm64-11`Frun_hook_wrapped + 20
    frame #23: 0x0000000104ebf16c Emacs-arm64-11`funcall_subr + 104
    frame #24: 0x0000000104efb554 Emacs-arm64-11`exec_byte_code + 2264
    frame #25: 0x0000000104ebf4e4 Emacs-arm64-11`funcall_lambda + 464
    frame #26: 0x0000000104ebf0b8 Emacs-arm64-11`funcall_general + 312
    frame #27: 0x0000000104ebb2a4 Emacs-arm64-11`Ffuncall + 176
    frame #28: 0x0000000104ebd45c Emacs-arm64-11`internal_condition_case_n + 116
    frame #29: 0x0000000104da68a8 Emacs-arm64-11`dsafe__call + 160
    frame #30: 0x0000000104da64e4 Emacs-arm64-11`dsafe_call1 + 88
    frame #31: 0x0000000104dbeaf4 Emacs-arm64-11`handle_fontified_prop + 812
    frame #32: 0x0000000104dbdc9c Emacs-arm64-11`handle_stop + 112
    frame #33: 0x0000000104dc0c7c Emacs-arm64-11`next_element_from_buffer + 236
    frame #34: 0x0000000104d9821c Emacs-arm64-11`get_next_display_element + 128
    frame #35: 0x0000000104daa370 Emacs-arm64-11`display_line + 956
    frame #36: 0x0000000104dcce10 Emacs-arm64-11`try_window_id + 2244
    frame #37: 0x0000000104dca260 Emacs-arm64-11`redisplay_window + 6032
    frame #38: 0x0000000104dc7e84 Emacs-arm64-11`redisplay_window_1 + 44
    frame #39: 0x0000000104ebd330 Emacs-arm64-11`internal_condition_case_1 + 96
    frame #40: 0x0000000104da5184 Emacs-arm64-11`redisplay_internal + 2976
    frame #41: 0x0000000104da8f30 Emacs-arm64-11`redisplay + 12
    frame #42: 0x0000000104e38edc Emacs-arm64-11`read_char + 720
    frame #43: 0x0000000104e37098 Emacs-arm64-11`read_key_sequence + 908
    frame #44: 0x0000000104e36244 Emacs-arm64-11`command_loop_1 + 680
    frame #45: 0x0000000104ebd2ac Emacs-arm64-11`internal_condition_case + 92
    frame #46: 0x0000000104e35f7c Emacs-arm64-11`command_loop_2 + 52
    frame #47: 0x0000000104ebcb1c Emacs-arm64-11`internal_catch + 80
    frame #48: 0x0000000104e35688 Emacs-arm64-11`command_loop + 308
    frame #49: 0x0000000104e354cc Emacs-arm64-11`recursive_edit_1 + 216
    frame #50: 0x0000000104e35894 Emacs-arm64-11`Frecursive_edit + 232
    frame #51: 0x0000000104e33710 Emacs-arm64-11`main + 4208
    frame #52: 0x0000000197ed0274 dyld`start + 2840
(lldb)
sogaiu commented 2 months ago

The trace looks slightly different this time:

  * frame #0: 0x000000019805c850 libsystem_malloc.dylib`nanov2_find_block_and_allocate + 368
    frame #1: 0x0000000198080798 libsystem_malloc.dylib`nanov2_allocate_outlined + 256
    frame #2: 0x000000019807fa70 libsystem_malloc.dylib`nanov2_malloc_type_zero_on_alloc + 488
    frame #3: 0x0000000104e937c4 Emacs-arm64-11`lmalloc + 44
    frame #4: 0x0000000104e93760 Emacs-arm64-11`xmalloc + 24
    frame #5: 0x0000000105945684 libtree-sitter.0.dylib`ts_stack_pop_count + 140

It seems to be memory-related again and tree-sitter is mentioned, but the function in tree-sitter is ts_stack_pop_count this time. Though it looks like that calls our friend stack__iter from the earlier trace.


Anyway, I found this page at the Emacs For Mac OS X site and it mentions that no patches are applied:

The scripts I run basically just configure and build right from the GNU source—I don't add any patches or any extraneous lisp packages. I do include the old Carbon icon on the disk image because I like it better than the new Cocoa icon but it is not enabled by default.

So perhaps this is why the Emacs Plus maintainer said:

Can you please try to reproduce with https://emacsformacosx.com/builds. If it's reproducible with 'bare' Emacs -> it needs to be reported to Emacs bug tracker.

since the emacsformacosx.com builds don't apply any patches, a logical next step might be the "Emacs bug tracker".

According to this FAQ:

Please see the Emacs manual for information on how to report bugs. See Checklist for Bug Reports in The GNU Emacs Manual.

Following the instructions there seems like a pretty involved process...

sogaiu commented 2 months ago

Ok, one of the steps was to check the etc/PROBLEMS file and when I did, I found the following:

* Emacs built with tree-sitter crashes when some -ts-mode is turned on.

The crash is in many cases an abort due to run-time detection of stack smashing, and it happens when one of the *-ts-mode modes is turned on in a buffer.

The reason is that the tree-sitter library changed its Application Binary Interface (ABI) between version 0.22.2 and 0.22.4, but did not increment the ABI version number. Therefore, Emacs compiled with tree-sitter versions before the change will try to use the shared library after the change, and crash due to incompatibilities in the ABI.

Until and unless the tree-sitter developers release a library > with an updated ABI version, the solution is to rebuild Emacs with the actual library with which it will be used. If you cannot rebuild Emacs, downgrade your tree-sitter library to version 0.22.2 or older.

The relevant tree-sitter issue is here:

https://github.com/tree-sitter/tree-sitter/issues/3296

via: https://github.com/emacs-mirror/emacs/blob/f283144658259f209efdef78c576b43832c9c479/etc/PROBLEMS#L219-L239

May be that's a possibility. There might be other relevant things in etc/PROBLEMS too. Perhaps worth a look?

vinurs commented 2 months ago

thanks for ur help. In my case, this issue doesn't cause Emacs to crash but instead causes it to freeze, with the CPU usage reaching 100%. Additionally, this doesn't happen every time, but only under certain unknown circumstances.

and my tree-sitter version

 brew info tree-sitter
==> tree-sitter: stable 0.23.0 (bottled), HEAD
Parser generator tool and incremental parsing library
https://tree-sitter.github.io/
Installed
/opt/homebrew/Cellar/tree-sitter/0.23.0 (15 files, 13.8MB) *
  Poured from bottle using the formulae.brew.sh API on 2024-08-27 at 04:56:39
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/t/tree-sitter.rb
License: MIT
==> Dependencies
Build: rust ✔
==> Options
--HEAD
        Install HEAD version
==> Analytics
install: 31,724 (30 days), 62,439 (90 days), 284,793 (365 days)
install-on-request: 2,643 (30 days), 4,233 (90 days), 22,216 (365 days)
build-error: 7 (30 days)

░▒▓   ~/tmp   16:08 
❯ tree-sitter --version
tree-sitter 0.23.0
sogaiu commented 2 months ago

Yes, it's true that the quoted item doesn't match because it's a crash. Thanks for the reminder to look for freezes.

I didn't find any other things that looked relevant or close in etc/PROBLEMS, though I may have missed something.


The next step mentioned is to look at "The GNU Bug Tracker at https://debbugs.gnu.org/". I guess this is what the Emacs Plus maintainer was referring to. Looking around there, it seems that this URL might be relevant.

I tried searching for "freeze" and "tree-sitter".

The closest thing I came across was this, though it's possible there are others. That isn't fixed yet, and it is currently being examined at the tree-sitter repository under this issue.


As you mentioned in this comment, Emacs 29 seems to work, right? I suggest using that for now if possible.

vinurs commented 2 months ago

i monitor its memory

#!/bin/bash
# 文件名: monitor_emacs_memory.sh

# 定义输出文件
output_file="emacs_memory_usage.log"

# 在文件中写入初始时间戳
echo "Monitoring started at $(date)" | tee -a "$output_file"

# 循环每5秒钟检查一次内存使用情况
while true; do
  # 获取内存使用情况,输出单位为KB
  memory_usage=$(ps -x -o rss,comm | grep '[E]macs' | awk '{print $1 " KB"}')

  # 获取当前时间戳
  timestamp=$(date +"%Y-%m-%d %H:%M:%S")

  # 将内存使用情况和时间戳写入文件同时输出到屏幕
  echo "$timestamp: $memory_usage" | tee -a "$output_file"

  # 等待5秒
  sleep 5
done

then output

 ./monitor_emacs_memory.sh
Monitoring started at Thu Sep 12 21:12:23 CST 2024
2024-09-12 21:12:23: 806624 KB
2024-09-12 21:12:28: 810720 KB
2024-09-12 21:12:33: 829840 KB
2024-09-12 21:12:38: 1582256 KB
2024-09-12 21:12:43: 4678816 KB
2024-09-12 21:12:48: 7831776 KB
2024-09-12 21:12:53: 10982384 KB
2024-09-12 21:12:58: 14140048 KB
2024-09-12 21:13:03: 17296176 KB
2024-09-12 21:13:08: 20440960 KB
2024-09-12 21:13:13: 23583008 KB
2024-09-12 21:13:18: 26726272 KB
2024-09-12 21:13:24: 29857312 KB
2024-09-12 21:13:29: 33011456 KB
2024-09-12 21:13:34: 36156624 KB
2024-09-12 21:13:39: 38685440 KB
2024-09-12 21:13:44: 34858560 KB
2024-09-12 21:13:49: 30892768 KB
2024-09-12 21:13:54: 26913888 KB
2024-09-12 21:13:59: 22790272 KB
2024-09-12 21:14:04: 18625232 KB
2024-09-12 21:14:09: 14512784 KB
2024-09-12 21:14:14: 10244960 KB
2024-09-12 21:14:19: 7949248 KB
2024-09-12 21:14:24: 7972448 KB
2024-09-12 21:14:30:
2024-09-12 21:14:35:

at last it was killed

vinurs commented 2 months ago

https://debbugs.gnu.org/cgi/bugreport.cgi?bug=73204 i report this to emacs

vinurs commented 2 months ago

has been fixed in the latest emacs-30

sogaiu commented 2 months ago

Glad to hear it seems to have worked out :)

Thanks for sharing the update on the situation.