file_manager: handle overlapped inotify watches
Handle exceptions raised when adding a new watch. Warn the user and skip adding the node to the watched tree. Signed-off-by: Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
parent
069a655df8
commit
7217b36f9b
|
@ -889,7 +889,8 @@ class InotifyNode:
|
||||||
item_path = os.path.join(dir_path, fname)
|
item_path = os.path.join(dir_path, fname)
|
||||||
if os.path.isdir(item_path):
|
if os.path.isdir(item_path):
|
||||||
new_child = self.create_child_node(fname, False)
|
new_child = self.create_child_node(fname, False)
|
||||||
metadata_events.extend(new_child.scan_node(visited_dirs))
|
if new_child is not None:
|
||||||
|
metadata_events.extend(new_child.scan_node(visited_dirs))
|
||||||
elif os.path.isfile(item_path) and self.get_root() == "gcodes":
|
elif os.path.isfile(item_path) and self.get_root() == "gcodes":
|
||||||
mevt = self.ihdlr.parse_gcode_metadata(item_path)
|
mevt = self.ihdlr.parse_gcode_metadata(item_path)
|
||||||
metadata_events.append(mevt)
|
metadata_events.append(mevt)
|
||||||
|
@ -972,11 +973,16 @@ class InotifyNode:
|
||||||
def create_child_node(self,
|
def create_child_node(self,
|
||||||
name: str,
|
name: str,
|
||||||
notify: bool = True
|
notify: bool = True
|
||||||
) -> InotifyNode:
|
) -> Optional[InotifyNode]:
|
||||||
self.flush_delete()
|
self.flush_delete()
|
||||||
if name in self.child_nodes:
|
if name in self.child_nodes:
|
||||||
return self.child_nodes[name]
|
return self.child_nodes[name]
|
||||||
new_child = InotifyNode(self.ihdlr, self, name)
|
try:
|
||||||
|
new_child = InotifyNode(self.ihdlr, self, name)
|
||||||
|
except Exception:
|
||||||
|
# This node is already watched under another root,
|
||||||
|
# bypass creation
|
||||||
|
return None
|
||||||
self.child_nodes[name] = new_child
|
self.child_nodes[name] = new_child
|
||||||
if notify:
|
if notify:
|
||||||
pending_node = self.search_pending_event("create_node")
|
pending_node = self.search_pending_event("create_node")
|
||||||
|
@ -1153,8 +1159,8 @@ class INotifyHandler:
|
||||||
) -> None:
|
) -> None:
|
||||||
self.server = config.get_server()
|
self.server = config.get_server()
|
||||||
self.event_loop = self.server.get_event_loop()
|
self.event_loop = self.server.get_event_loop()
|
||||||
self.debug_enabled = config['server'].getboolean(
|
self.debug_enabled = self.server.is_debug_enabled()
|
||||||
'enable_debug_logging', False)
|
self.enable_warn = config.getboolean("enable_inotify_warnings", True)
|
||||||
self.file_manager = file_manager
|
self.file_manager = file_manager
|
||||||
self.gcode_metadata = gcode_metadata
|
self.gcode_metadata = gcode_metadata
|
||||||
self.inotify = INotify(nonblocking=True)
|
self.inotify = INotify(nonblocking=True)
|
||||||
|
@ -1177,7 +1183,10 @@ class INotifyHandler:
|
||||||
old_root = self.watched_roots.pop(root)
|
old_root = self.watched_roots.pop(root)
|
||||||
old_root.clear_watches()
|
old_root.clear_watches()
|
||||||
old_root.clear_events()
|
old_root.clear_events()
|
||||||
root_node = InotifyRootNode(self, root, root_path)
|
try:
|
||||||
|
root_node = InotifyRootNode(self, root, root_path)
|
||||||
|
except Exception:
|
||||||
|
return
|
||||||
self.watched_roots[root] = root_node
|
self.watched_roots[root] = root_node
|
||||||
if self.initialized:
|
if self.initialized:
|
||||||
mevts = root_node.scan_node()
|
mevts = root_node.scan_node()
|
||||||
|
@ -1213,9 +1222,31 @@ class INotifyHandler:
|
||||||
dir_path = node.get_path()
|
dir_path = node.get_path()
|
||||||
try:
|
try:
|
||||||
watch: int = self.inotify.add_watch(dir_path, WATCH_FLAGS)
|
watch: int = self.inotify.add_watch(dir_path, WATCH_FLAGS)
|
||||||
except OSError:
|
except Exception:
|
||||||
logging.exception(
|
msg = (
|
||||||
f"Error adding watch, already exists: {dir_path}")
|
f"Error adding inotify watch to root '{node.get_root()}', "
|
||||||
|
f"path: {dir_path}"
|
||||||
|
)
|
||||||
|
logging.exception(msg)
|
||||||
|
if self.enable_warn:
|
||||||
|
msg = f"file_manager: {msg}"
|
||||||
|
self.server.add_warning(msg, log=False)
|
||||||
|
raise
|
||||||
|
if watch in self.watched_nodes:
|
||||||
|
root = node.get_root()
|
||||||
|
cur_node = self.watched_nodes[watch]
|
||||||
|
existing_root = cur_node.get_root()
|
||||||
|
msg = (
|
||||||
|
f"Inotify watch already exists for path '{dir_path}' in "
|
||||||
|
f"root '{existing_root}', cannot add watch to requested root "
|
||||||
|
f"'{root}'. This indicates that the roots overlap."
|
||||||
|
)
|
||||||
|
if self.enable_warn:
|
||||||
|
msg = f"file_manager: {msg}"
|
||||||
|
self.server.add_warning(msg)
|
||||||
|
else:
|
||||||
|
logging.info(msg)
|
||||||
|
raise self.server.error("Watch already exists")
|
||||||
self.watched_nodes[watch] = node
|
self.watched_nodes[watch] = node
|
||||||
return watch
|
return watch
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue