helm-ag 导致崩溃问题以及 debug 思路求助

求助本坛的大佬,如何调试一个 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

试了各种调试办法,完全抓不到出错的点。智慧不够用了,求各位大佬指点迷津。

提供一个思路,profile 一下,看看那个函数在反复执行(卡死),然后阅读对应代码。

或者可以去给 helm 提 issue,以寻求帮助。

你只讲了你的猜测,很多必要的信息你没提供。是你自己写的 async source,还是 helm 内置的也都不知道。讨论不能建立在不确定的信息基础上。

最好整理出一份最小配置,附上详细步骤,让别人可以重现你的问题。

多谢! :+1: 我试了一下,有新的发现:

         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,就会出现这种问题。复现步骤:

  1. 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\\'")))
  1. 调用 helm-ag-do-project-root 进行搜索,关键字用 “|helm” 就可以重现这个问题,|前为空。 这种search pattern会导致rg把所有 root 目录下的文件每行都匹配上。

完全找不到 “minibuffer-error-function” 在哪调用的。。。

确认了,这个bug和我提的那个pr没任何关系,在helm-ag main latest上就能重现。我已经开了个issue。

  1. root 目录规模多大?

  2. fuzzy match 匹配很宽松:

    (let ((r (helm--mapconcat-pattern "foo")))
      (mapcar (lambda (s)
                (string-match-p r s))
              '("foobar"
                "fobaro"
                "fbaroo"
                "fboaor")))
    ;; => (0 0 0 0)
    

链接在哪里?

root 目录规模多大?

我测试的目录并不大,helm-ag 这个repo下测试就会挂掉。代码1000多行。

链接在哪

可能是正则表达式处理不当导致的问题。

我知道出错原因了。

解决之前需先厘清一个问题:你认为 | 是什么?

  1. 字面上的 | 符号。
  2. 正则表达式的或操作。

其实不管 | 在前或在后都有问题,我提交了一个简单的修复:

多谢大神啊,问题解决了,不过非常好奇你是如何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 思路求助

正则表达式是高级用户的必修课。

多谢指教 :pray: 我其实知道是正则过于宽泛导致的,但是开始是怀疑这个导致结果集太大,candidate-process进程无法结束,但后来发现其实helm每次都会kill老的进程。highlight-candidate这个真的没trace到… 刚刚尝试debug,智慧不够啊。应该自己写些log来辅助debug。