Skip to content

Commit 744a8ae

Browse files
committed
fix(#3198): add filesystem_watchers.max_outstanding_events which disables filesystem watchers on a directory when runaway events are received
1 parent 89d9621 commit 744a8ae

File tree

4 files changed

+34
-5
lines changed

4 files changed

+34
-5
lines changed

doc/nvim-tree-lua.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2987,6 +2987,7 @@ Following is the default configuration, see |nvim_tree.config| for details. >lua
29872987
filesystem_watchers = {
29882988
enable = true,
29892989
debounce_delay = 50,
2990+
max_outstanding_events = 100,
29902991
ignore_dirs = {
29912992
"/.ccls-cache",
29922993
"/build",

lua/nvim-tree.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,7 @@ local DEFAULT_OPTS = { -- default-config-start
462462
filesystem_watchers = {
463463
enable = true,
464464
debounce_delay = 50,
465+
max_outstanding_events = 100,
465466
ignore_dirs = {
466467
"/.ccls-cache",
467468
"/build",

lua/nvim-tree/explorer/watch.lua

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
local log = require("nvim-tree.log")
22
local git = require("nvim-tree.git")
33
local utils = require("nvim-tree.utils")
4+
local notify = require("nvim-tree.notify")
45
local Watcher = require("nvim-tree.watcher").Watcher
56

67
local M = {
@@ -69,10 +70,30 @@ function M.create_watcher(node)
6970
---@param watcher Watcher
7071
local function callback(watcher)
7172
log.line("watcher", "node event scheduled refresh %s", watcher.data.context)
73+
74+
-- event is awaiting debouncing and handling
75+
watcher.data.outstanding_events = watcher.data.outstanding_events + 1
76+
77+
-- disable watcher when outstanding exceeds max
78+
if watcher.data.outstanding_events > M.config.filesystem_watchers.max_outstanding_events then
79+
notify.error(string.format(
80+
"Observed %d consecutive file system events with interval < %dms, exceeding filesystem_watchers.max_events=%s. Disabling watcher for directory '%s'. Consider adding this directory to filesystem_watchers.ignore_dirs",
81+
watcher.data.outstanding_events,
82+
M.config.filesystem_watchers.max_outstanding_events,
83+
M.config.filesystem_watchers.debounce_delay,
84+
node.absolute_path
85+
))
86+
node:destroy_watcher()
87+
end
88+
7289
utils.debounce(watcher.data.context, M.config.filesystem_watchers.debounce_delay, function()
7390
if watcher.destroyed then
7491
return
7592
end
93+
94+
-- event has been handled
95+
watcher.data.outstanding_events = 0
96+
7697
if node.link_to then
7798
log.line("watcher", "node event executing refresh '%s' -> '%s'", node.link_to, node.absolute_path)
7899
else
@@ -87,7 +108,8 @@ function M.create_watcher(node)
87108
path = path,
88109
callback = callback,
89110
data = {
90-
context = "explorer:watch:" .. path .. ":" .. M.uid
111+
context = "explorer:watch:" .. path .. ":" .. M.uid,
112+
outstanding_events = 0, -- unprocessed events that have not been debounced
91113
}
92114
})
93115
end

lua/nvim-tree/node/directory.lua

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,7 @@ function DirectoryNode:new(args)
3737
end
3838

3939
function DirectoryNode:destroy()
40-
if self.watcher then
41-
self.watcher:destroy()
42-
self.watcher = nil
43-
end
40+
self:destroy_watcher()
4441

4542
if self.nodes then
4643
for _, node in pairs(self.nodes) do
@@ -51,6 +48,14 @@ function DirectoryNode:destroy()
5148
Node.destroy(self)
5249
end
5350

51+
---Halt and remove the watcher for this node
52+
function DirectoryNode:destroy_watcher()
53+
if self.watcher then
54+
self.watcher:destroy()
55+
self.watcher = nil
56+
end
57+
end
58+
5459
---Update the git_status of the directory
5560
---@param parent_ignored boolean
5661
---@param project GitProject?

0 commit comments

Comments
 (0)