universal-ctags/citre

emacs stuck in citre-get-output-lines

Opened this issue · 6 comments

t6ui commented

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

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

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.

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)

@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.

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

@tangxinfa

We need steps to reproduce

Read this again.