mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-23 04:53:12 -08:00
Eglot: limit the number of file watches
Some language servers request file watching for a very large number of directories (e.g. Python virtualenvs), which can exhaust system resources and cause slow startup. https://github.com/joaotavora/eglot/issues/1568 * lisp/progmodes/eglot.el (eglot-max-file-watches): New variable. (eglot--count-file-watches): New function. (eglot--watch-globs): Use them to limit watches. Signal jsonrpc-error when limit is reached. (eglot-watch-files-outside-project-root): Fix docstring punctuation. * etc/EGLOT-NEWS: Mention change.
This commit is contained in:
parent
a3ea65a984
commit
d3548aea96
2 changed files with 38 additions and 5 deletions
|
|
@ -20,6 +20,13 @@ https://github.com/joaotavora/eglot/issues/1234.
|
|||
|
||||
* Changes to upcoming Eglot
|
||||
|
||||
** File watch limits to prevent resource exhaustion (github#1568)
|
||||
|
||||
The new variable 'eglot-max-file-watches' limits the number of file
|
||||
watches that can be created. Some language servers request watching
|
||||
for a very large number of directories (e.g. Python virtualenvs), which
|
||||
can exhaust system resources and cause slow startup.
|
||||
|
||||
** Support for complex workspace edits (create/rename/delete files)
|
||||
|
||||
Eglot now advertises support for file resource operations in workspace
|
||||
|
|
|
|||
|
|
@ -4680,11 +4680,28 @@ at point. With prefix argument, prompt for ACTION-KIND."
|
|||
;;; File watchers (aka didChangeWatchedFiles)
|
||||
;;;
|
||||
(defvar eglot-watch-files-outside-project-root t
|
||||
"If non-nil, allow watching files outside project root")
|
||||
"If non-nil, allow watching files outside project root.")
|
||||
|
||||
(defvar eglot-max-file-watches 10000
|
||||
"Maximum number of file watches across all Eglot servers.
|
||||
If this limit is reached, a warning is issued and further watches
|
||||
are not added. Set to nil for unlimited watches.")
|
||||
|
||||
(defun eglot--count-file-watches ()
|
||||
"Count total file watches across all Eglot servers."
|
||||
(let ((count 0))
|
||||
(maphash (lambda (_proj servers)
|
||||
(dolist (server servers)
|
||||
(maphash (lambda (_id descs)
|
||||
(cl-incf count (length descs)))
|
||||
(eglot--file-watches server))))
|
||||
eglot--servers-by-project)
|
||||
count))
|
||||
|
||||
(cl-defun eglot--watch-globs (server id globs dir in-root
|
||||
&aux (project (eglot--project server))
|
||||
success)
|
||||
success
|
||||
(watch-count (eglot--count-file-watches)))
|
||||
"Set up file watching for relative file names matching GLOBS under DIR.
|
||||
GLOBS is a list of (COMPILED-GLOB . KIND) pairs, where COMPILED-GLOB is
|
||||
a compiled glob predicate and KIND is a bitmask of change types. DIR is
|
||||
|
|
@ -4727,9 +4744,18 @@ happens to be inside or matching the project root."
|
|||
(handle-event `(,desc deleted ,file))
|
||||
(handle-event `(,desc created ,file1))))))
|
||||
(add-watch (subdir)
|
||||
(when (file-readable-p subdir)
|
||||
(push (file-notify-add-watch subdir '(change) #'handle-event)
|
||||
(gethash id (eglot--file-watches server))))))
|
||||
(cond ((not (file-readable-p subdir)))
|
||||
((and eglot-max-file-watches
|
||||
(>= watch-count eglot-max-file-watches))
|
||||
(eglot--warn "Reached `eglot-max-file-watches' limit of %d, \
|
||||
not watching some directories" eglot-max-file-watches)
|
||||
;; Could `(setq success t)' here to keep partial watches.
|
||||
(jsonrpc-error "Reached `eglot-max-file-watches' limit of %d"
|
||||
eglot-max-file-watches))
|
||||
(t
|
||||
(push (file-notify-add-watch subdir '(change) #'handle-event)
|
||||
(gethash id (eglot--file-watches server)))
|
||||
(cl-incf watch-count)))))
|
||||
(let ((subdirs (if (or (null dir) in-root)
|
||||
(subdirs-using-project)
|
||||
(condition-case _ (subdirs-using-find)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue