求助本坛的大佬,如何调试一个 emacs 死循环的问题。
背景是,我在调试一个 emacs helm (GitHub - emacs-helm/helm: Emacs incremental completion and selection narrowing framework) 的插件,用到了async-source,也就是后台调用一个async的process来生成补全candidates。目前当这个 process 生成的结果集太大的时候,emacs就感觉死循环了,在mini-buffer直接打印出下面的错误:
死几秒中之后,最后的错误信息:
progn: End of buffer [203 times]
while: Variable binding depth exceeds max-specpdl-size
and: Variable binding depth exceeds max-specpdl-size
let: Variable binding depth exceeds max-specpdl-size
Error during redisplay: (#[128 "\300\301^B\"\210\300\302^B\"\207" [apply redisplay--pre-redisplay-functions ignore nil] 4 nil nil] nil) signaled$
sit-for: Variable binding depth exceeds max-specpdl-size
试了各种调试办法,完全抓不到出错的点。智慧不够用了,求各位大佬指点迷津。
zerol
2
提供一个思路,profile 一下,看看那个函数在反复执行(卡死),然后阅读对应代码。
或者可以去给 helm 提 issue,以寻求帮助。
你只讲了你的猜测,很多必要的信息你没提供。是你自己写的 async source,还是 helm 内置的也都不知道。讨论不能建立在不确定的信息基础上。
最好整理出一份最小配置,附上详细步骤,让别人可以重现你的问题。
多谢!
我试了一下,有新的发现:
510 85% - command-execute
510 85% - funcall-interactively
424 71% - helm-do-ag-project-root
424 71% - let
424 71% - helm-do-ag
424 71% - let*
424 71% - if
424 71% - helm-do-ag--helm
424 71% - let
423 70% - helm
423 70% - helm
423 70% - helm-internal
422 70% - helm-read-from-minibuffer
413 69% - minibuffer-error-function
413 69% - minibuffer-message
413 69% - sit-for
412 69% - minibuffer-error-function
412 69% - minibuffer-message
412 69% - sit-for
410 68% - minibuffer-error-function
410 68% - minibuffer-message
409 68% - sit-for
409 68% - minibuffer-error-function
409 68% - minibuffer-message
409 68% - sit-for
408 68% - minibuffer-error-function
408 68% - minibuffer-message
407 68% - sit-for
401 67% - minibuffer-error-function
400 67% - minibuffer-message
395 66% - sit-for
2 0% - minibuffer-error-function
1 0% substitute-command-keys
1 0% - redisplay_internal (C function)
1 0% tty-color-desc
1 0% + substitute-command-keys
4 0% + helm-output-filter
得再看看code
不好意思,忘了描述了,本来想快速请教一下有没有debug的思路。
不是我自己的写的async source,我是给helm-ag提了个pr,稍微改了一下 helm-do-ag,想让它更好的支持 “rg” Further Support "rg" Backend by zozowell · Pull Request #394 · emacsorphanage/helm-ag · GitHub
大部分时间都挺好用的,但是只要是search pattern里包含一个空pattern,就会出现这种问题。复现步骤:
- helm-ag 配置
(use-package helm-ag
:ensure nil
:load-path "~/.emacs.d/packages/helm-ag/"
:config
(setq helm-ag-base-command "rg --no-heading")
(setq helm-ag-success-exit-status '(0 2))
(setq helm-ag-fuzzy-match t)
(setq helm-ag-insert-at-point 'symbol)
(setq helm-ag-ignore-patterns '("node_modules" "workspaces"))
(setq helm-ag-ignore-buffer-patterns '("\\.txt\\'" "\\.mkd\\'")))
- 调用 helm-ag-do-project-root 进行搜索,关键字用 “|helm” 就可以重现这个问题,|前为空。
这种search pattern会导致rg把所有 root 目录下的文件每行都匹配上。
完全找不到 “minibuffer-error-function” 在哪调用的。。。
确认了,这个bug和我提的那个pr没任何关系,在helm-ag main latest上就能重现。我已经开了个issue。
root 目录规模多大?
我测试的目录并不大,helm-ag 这个repo下测试就会挂掉。代码1000多行。
链接在哪
其实不管 |
在前或在后都有问题,我提交了一个简单的修复:
多谢大神啊,问题解决了,不过非常好奇你是如何debug的,怎么能trace到这个地方,感谢指教一二。
对于你的问题,其实当成字符| 是比较好的,但是需要做进一步 escape 转换。当成正则比较简单了就。而且行为和 helm-do-ag 是一致的,所以感觉可以接受。
看到 |
自然而然想到是正则表达式的问题。
不过刚开始被你误导,以为是项目规模大、匹配结果太多。所以说,把问题描述清楚很重要。
既然怀疑正则表达式有问题,就把 helm ag 转换的 search pattern 打印出来看看。然后就知道 |foo
在 helm ag 是作为 OR 表达式对待。
然后顺着 helm ag class/source 定义往下找。先看 rg 命令有没有问题。rg 命令执行无误,再看 Emacs 这头渲染 helm buffer 是不是有问题。
很容易就发现 helm-do-ag--filter-one-by-one
有问题,再往下追就发现 helm-ag--highlight-string-matched
中的 while 循环越界。
自己打印 message 目标明确利于观察,helm-log 内容太杂太多难懂。
1 个赞
更改了标题:
- elisp debug 问题求助
+ helm-ag 导致崩溃问题以及 debug 思路求助
多谢指教
我其实知道是正则过于宽泛导致的,但是开始是怀疑这个导致结果集太大,candidate-process进程无法结束,但后来发现其实helm每次都会kill老的进程。highlight-candidate这个真的没trace到… 刚刚尝试debug,智慧不够啊。应该自己写些log来辅助debug。