universal-ctags / citre

A superior code reading & auto-completion tool with pluggable backends.
GNU General Public License v3.0
321 stars 25 forks source link

emacs stuck in citre-get-output-lines #171

Open t6ui opened 2 months ago

t6ui commented 2 months ago

Sometimes emacs becomes unresponsive, I issue the command pkill -SIGUSR2 emacs to obtain a stack trace. Below is the output of the stack trace generated during a freeze. What might be causing this issue, and is there a way to resolve it?

Debugger entered--entering a function:
* #f(compiled-function () #<bytecode -0xa31b8a984746886>)()
  citre-get-output-lines(("readtags" "-t" "/workspace/apps/emacs.d/purcell/.cache/tags/!works..." "-Q" "(and $name (eq? $name \"!_TAG_PROC_CWD\"))" "-Ene" "-D"))
  citre-readtags--get-lines("/workspace/apps/emacs.d/purcell/.cache/tags/!works..." nil nil nil (and $name (eq? $name "!_TAG_PROC_CWD")) nil "-D")
  citre-readtags-get-pseudo-tags("TAG_PROC_CWD" "/workspace/apps/emacs.d/purcell/.cache/tags/!works...")
  citre-readtags--fetch-tags-file-info("/workspace/apps/emacs.d/purcell/.cache/tags/!works...")
  citre-readtags-tags-file-info("/workspace/apps/emacs.d/purcell/.cache/tags/!works...")
  citre-readtags-filter-input("/workspace/apps/emacs.d/purcell/.emacs.d/elpa-29.1..." "/workspace/apps/emacs.d/purcell/.cache/tags/!works...")
  citre-tags--imenu-tags-from-tags-file()
  citre-tags-get-tags-in-buffer()
  apply(citre-tags-get-tags-in-buffer nil)
  citre--try-func-in-backend-list(get-tags-in-buffer-func #<hash-table eq 2/5 0x1ec76bf> (tags global))
  citre-get-backend-and-tags-in-buffer()
  citre-get-tags-in-buffer()
  citre-imenu-create-index-function()
  package-lint--get-defs()
  package-lint--check-all()
  package-lint-buffer()
  package-lint-flymake(#f(compiled-function (&rest args) #<bytecode 0x15745dcccad7f884>))
  apply(package-lint-flymake #f(compiled-function (&rest args) #<bytecode 0x15745dcccad7f884>) nil)
  flymake--run-backend(package-lint-flymake nil)
  #f(compiled-function (backend) #<bytecode -0x1ba4c3046678fc01>)(package-lint-flymake)
  run-hook-wrapped(#f(compiled-function (backend) #<bytecode -0x1ba4c3046678fc01>) package-lint-flymake)
  flymake-start((on-display) nil)
  #f(compiled-function () #<bytecode -0xb8d506121e631eb>)()

or

Debugger entered--entering a function:
* substitute-command-keys("Quit")
  accept-process-output()
  citre-get-output-lines(("readtags" "-t" "/workspace/apps/emacs.d/purcell/.cache/tags/!works..." "-Q" "(and (or (and $input (eq? $input \"/workspace/apps/..." "-S" "(<or> (if (and $line &line) (<> $line &line) 0))" "-Ene" "-l"))
  citre-readtags--get-lines("/workspace/apps/emacs.d/purcell/.cache/tags/!works..." nil nil nil (and (or (and $input (eq? $input "/workspace/apps/emacs.d/purcell/.emacs.d/elpa-29.1...")) (and $input (eq? $input "elpa-29.1/citre-20240203.457/citre-common-util.el")) (and $input ((string->regexp "(^|/)..?/citre-common-util\\.el$" :case-fold false) $input))) (not (or (and $extras ((string->regexp "(^|,) ?(anonymous|inputFile)(,|$)" :case-fold false) $extras)) (and $kind ((string->regexp "^(file|F)$" :case-fold false) $kind))))) (<or> (if (and $line &line) (<> $line &line) 0)) nil)
  citre-readtags--get-tags("/workspace/apps/emacs.d/purcell/.cache/tags/!works..." nil nil nil :filter (and (or (and $input (eq? $input "/workspace/apps/emacs.d/purcell/.emacs.d/elpa-29.1...")) (and $input (eq? $input "elpa-29.1/citre-20240203.457/citre-common-util.el")) (and $input ((string->regexp "(^|/)..?/citre-common-util\\.el$" :case-fold false) $input))) (not (or (and $extras ((string->regexp "(^|,) ?(anonymous|inputFile)(,|$)" :case-fold false) $extras)) (and $kind ((string->regexp "^(file|F)$" :case-fold false) $kind))))) :sorter (<or> (if (and $line &line) (<> $line &line) 0)) :require (name pattern) :optional (ext-kind-full line typeref scope extras) :exclude nil :parse-all-fields nil)
  citre-readtags-get-tags("/workspace/apps/emacs.d/purcell/.cache/tags/!works..." nil nil nil :filter (and (or (and $input (eq? $input "/workspace/apps/emacs.d/purcell/.emacs.d/elpa-29.1...")) (and $input (eq? $input "elpa-29.1/citre-20240203.457/citre-common-util.el")) (and $input ((string->regexp "(^|/)..?/citre-common-util\\.el$" :case-fold false) $input))) (not (or (and $extras ((string->regexp "(^|,) ?(anonymous|inputFile)(,|$)" :case-fold false) $extras)) (and $kind ((string->regexp "^(file|F)$" :case-fold false) $kind))))) :sorter (<or> (if (and $line &line) (<> $line &line) 0)) :require (name pattern) :optional (ext-kind-full line typeref scope extras) :exclude nil :parse-all-fields nil)
  citre-tags-get-tags("/workspace/apps/emacs.d/purcell/.cache/tags/!works..." nil nil :filter (and (or (and $input (eq? $input "/workspace/apps/emacs.d/purcell/.emacs.d/elpa-29.1...")) (and $input (eq? $input "elpa-29.1/citre-20240203.457/citre-common-util.el")) (and $input ((string->regexp "(^|/)..?/citre-common-util\\.el$" :case-fold false) $input))) (not (or (and $extras ((string->regexp "(^|,) ?(anonymous|inputFile)(,|$)" :case-fold false) $extras)) (and $kind ((string->regexp "^(file|F)$" :case-fold false) $kind))))) :sorter (<or> (if (and $line &line) (<> $line &line) 0)) :require (name pattern) :optional (ext-kind-full line typeref scope extras))
  citre-tags--imenu-tags-from-tags-file()
  citre-tags-get-tags-in-buffer()
  apply(citre-tags-get-tags-in-buffer nil)
  citre--try-func-in-backend-list(get-tags-in-buffer-func #<hash-table eq 2/5 0x1ec76bf> (tags global))
  citre-get-backend-and-tags-in-buffer()
  citre-get-tags-in-buffer()
  citre-imenu-create-index-function()
  package-lint--get-defs()
  package-lint--check-all()
  package-lint-buffer()
  package-lint-flymake(#f(compiled-function (&rest args) #<bytecode 0x1788c869f97f884>))
  apply(package-lint-flymake #f(compiled-function (&rest args) #<bytecode 0x1788c869f97f884>) nil)
  flymake--run-backend(package-lint-flymake nil)
  #f(compiled-function (backend) #<bytecode -0x1ba4c3046678fc01>)(package-lint-flymake)
  run-hook-wrapped(#f(compiled-function (backend) #<bytecode -0x1ba4c3046678fc01>) package-lint-flymake)
  flymake-start(t)
  flymake-after-save-hook()
  run-hooks(after-save-hook)
  basic-save-buffer()
  (progn (if with-temp-message (progn (setq current-message (current-message)) (message "%s" with-temp-message))) (basic-save-buffer))
  (unwind-protect (progn (if with-temp-message (progn (setq current-message (current-message)) (message "%s" with-temp-message))) (basic-save-buffer)) (and with-temp-message (if current-message (message "%s" current-message) (message nil))))
  (let ((with-temp-message "") (current-message)) (unwind-protect (progn (if with-temp-message (progn (setq current-message (current-message)) (message "%s" with-temp-message))) (basic-save-buffer)) (and with-temp-message (if current-message (message "%s" current-message) (message nil)))))
  (if auto-save-slient (let ((with-temp-message "") (current-message)) (unwind-protect (progn (if with-temp-message (progn (setq current-message (current-message)) (message "%s" with-temp-message))) (basic-save-buffer)) (and with-temp-message (if current-message (message "%s" current-message) (message nil))))) (basic-save-buffer))
  (progn (setq autosave-buffer-list (cons (buffer-name) autosave-buffer-list)) (if auto-save-slient (let ((with-temp-message "") (current-message)) (unwind-protect (progn (if with-temp-message (progn (setq current-message ...) (message "%s" with-temp-message))) (basic-save-buffer)) (and with-temp-message (if current-message (message "%s" current-message) (message nil))))) (basic-save-buffer)))
  (if (and (buffer-file-name) (buffer-modified-p) (file-writable-p (buffer-file-name)) (auto-save-include-p (buffer-file-name))) (progn (setq autosave-buffer-list (cons (buffer-name) autosave-buffer-list)) (if auto-save-slient (let ((with-temp-message "") (current-message)) (unwind-protect (progn (if with-temp-message (progn ... ...)) (basic-save-buffer)) (and with-temp-message (if current-message (message "%s" current-message) (message nil))))) (basic-save-buffer))))
  (let ((buf (car tail))) (set-buffer buf) (if (and (buffer-file-name) (buffer-modified-p) (file-writable-p (buffer-file-name)) (auto-save-include-p (buffer-file-name))) (progn (setq autosave-buffer-list (cons (buffer-name) autosave-buffer-list)) (if auto-save-slient (let ((with-temp-message "") (current-message)) (unwind-protect (progn (if with-temp-message ...) (basic-save-buffer)) (and with-temp-message (if current-message ... ...)))) (basic-save-buffer)))) (setq tail (cdr tail)))
  (while tail (let ((buf (car tail))) (set-buffer buf) (if (and (buffer-file-name) (buffer-modified-p) (file-writable-p (buffer-file-name)) (auto-save-include-p (buffer-file-name))) (progn (setq autosave-buffer-list (cons (buffer-name) autosave-buffer-list)) (if auto-save-slient (let ((with-temp-message "") (current-message)) (unwind-protect (progn ... ...) (and with-temp-message ...))) (basic-save-buffer)))) (setq tail (cdr tail))))
  (let ((tail (buffer-list))) (while tail (let ((buf (car tail))) (set-buffer buf) (if (and (buffer-file-name) (buffer-modified-p) (file-writable-p (buffer-file-name)) (auto-save-include-p (buffer-file-name))) (progn (setq autosave-buffer-list (cons (buffer-name) autosave-buffer-list)) (if auto-save-slient (let (... ...) (unwind-protect ... ...)) (basic-save-buffer)))) (setq tail (cdr tail)))))
  (save-excursion (let ((tail (buffer-list))) (while tail (let ((buf (car tail))) (set-buffer buf) (if (and (buffer-file-name) (buffer-modified-p) (file-writable-p (buffer-file-name)) (auto-save-include-p (buffer-file-name))) (progn (setq autosave-buffer-list (cons ... autosave-buffer-list)) (if auto-save-slient (let ... ...) (basic-save-buffer)))) (setq tail (cdr tail))))) (if auto-save-slient nil (cond ((= (length autosave-buffer-list) 1) (message "# Saved %s" (car autosave-buffer-list))) ((> (length autosave-buffer-list) 1) (message "# Saved %d files: %s" (length autosave-buffer-list) (mapconcat 'identity autosave-buffer-list ", "))))))
  (let* (autosave-buffer-list) (save-excursion (let ((tail (buffer-list))) (while tail (let ((buf (car tail))) (set-buffer buf) (if (and (buffer-file-name) (buffer-modified-p) (file-writable-p ...) (auto-save-include-p ...)) (progn (setq autosave-buffer-list ...) (if auto-save-slient ... ...))) (setq tail (cdr tail))))) (if auto-save-slient nil (cond ((= (length autosave-buffer-list) 1) (message "# Saved %s" (car autosave-buffer-list))) ((> (length autosave-buffer-list) 1) (message "# Saved %d files: %s" (length autosave-buffer-list) (mapconcat 'identity autosave-buffer-list ", ")))))))
  auto-save-buffers()
  apply(auto-save-buffers nil)
  timer-event-handler([t 0 2 0 t auto-save-buffers nil idle 0 nil])
t6ui commented 2 months ago

During the instances when Emacs freezes, I notice that readtags executes briefly but then quickly terminates, yet Emacs remains unresponsive and stuck.

AmaiKinono commented 2 months ago

Emacs stucks because it runs into an infinite loop containing a accept-process-output call, which is due to that the process finish signal is not properly captured.

I haven't ran into such a problem in recent years, but I do got Windows users reporting this problem, and have modified the mechanism in Citre several times for this. It seems you are using Linux, right?

Honestly I don't know how it happens. If you are willing to look into it, please read the source code of citre-get-output-lines. I would also guess updating your Emacs version to maybe 28 or 29 may fix the problem, based on my vague memory.

tangxinfa commented 2 months ago

The same problem occurred after upgrade emacs and reinstall all elpa packages:

GNU Emacs 29.3 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.41, cairo version 1.18.0)
AmaiKinono commented 2 months ago

@tangxinfa Citre developes have not succeeded in reproducing the problem, so letting us know it happens simply doesn't help. We need steps to reproduce, and the first step should be emacs -Q so developers could actually try it out.

tangxinfa commented 2 months ago

After emacs stuck, when i press C-g, the minibuffer willl ouput "Quit emacsclient request"

AmaiKinono commented 2 months ago

@tangxinfa

We need steps to reproduce

Read this again.