Eglot causes lock up when language server tries to watch files in large directoryΒ #1258
Description
I'm using Eglot with nil, a language server for the Nix language. This language server wants to watch two files in the current directory over LSP protocol, which causes a find process to be spawned:
find -H . ( -path */SCCS/* -o -path */RCS/* -o [...] -o -path *.pyc -o -path *.pyo ) -prune -o -type f -print0
Since this recursively searches the whole current working directory, it can take a very long time to get the effect the language server wants (to watch files ./flake.nix and ./flake.lock), when running in a large directory such as the user home. (As a workaround, the find process can be killed.)
Here's the event buffer log (whole log):
[server-request] (id:1) Sat Jul 29 21:12:16 2023:
(:jsonrpc "2.0" :id 1 :method "client/registerCapability" :params
(:registrations
[(:id "workspace/didChangeWatchedFiles" :method "workspace/didChangeWatchedFiles" :registerOptions
(:watchers
[(:globPattern "/home/saiko/flake.lock")
(:globPattern "/home/saiko/flake.nix")]))]))
[client-reply] (id:1) ERROR Sat Jul 29 21:13:35 2023:
(:jsonrpc "2.0" :id 1 :error
(:code -32603 :message "Internal error"))
(the internal error is a result of me killing the find process)
See oxalica/nil#98. This also has a debugger backtrace (thanks @sauricat!)
Minimum reproducible example
- Get Emacs, Eglot, nix-mode (for setting up eglot to run nil in .nix files) and the nil language server
- Using the Nix package manager: Run
nix develop --impure --expr 'let pkgs = import (builtins.getFlake "nixpkgs/11cf5e1c74fe6892e860afeeaf3bfb84fdb7b1c3") {}; in pkgs.mkShell { buildInputs = [pkgs.nil ((pkgs.emacsPackagesFor pkgs.emacs-nox).emacsWithPackages (epkgs: [epkgs.nix-mode epkgs.eglot]))]; }'
to open a shell with the necessary packages and Emacs configured to load plugins - Manually install Emacs 28.2, eglot 1.15, nix-mode 1.5.0, nil 2023-05-09 (these are the same versions as you get with the Nix command)
- Run
emacs ~/test.nix
(or a file in any other large directory). The file doesn't have to exist. - Enable eglot, M-x eglot
- Emacs starts the language server, last status line being something like "[eglot] Connected! Server `nil' now managing `(nix-mode)' buffers in project `saiko'."
- Emacs waits for the find process