Skip to content

Eglot causes lock up when language server tries to watch files in large directoryΒ #1258

Open
@2xsaiko

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

  1. 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)
  1. Run emacs ~/test.nix (or a file in any other large directory). The file doesn't have to exist.
  2. Enable eglot, M-x eglot
  3. Emacs starts the language server, last status line being something like "[eglot] Connected! Server `nil' now managing `(nix-mode)' buffers in project `saiko'."
  4. Emacs waits for the find process

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions