diff --git a/fail2ban/server/filterpyinotify.py b/fail2ban/server/filterpyinotify.py index d63d1de6..ef26303a 100644 --- a/fail2ban/server/filterpyinotify.py +++ b/fail2ban/server/filterpyinotify.py @@ -225,22 +225,27 @@ class FilterPyinotify(FileFilter): self.__watchFiles.update(wd) logSys.debug("Added file watcher for %s", path) + def _delWatch(self, wdInt): + m = self.__monitor + try: + if m.get_path(wdInt) is not None: + wd = m.rm_watch(wdInt, quiet=False) + return True + except pyinotify.WatchManagerError as e: + if m.get_path(wdInt) is not None and not str(e).endswith("(EINVAL)"): # prama: no cover + logSys.debug("Remove watch causes: %s", e) + raise e + return False + def _delFileWatcher(self, path): try: wdInt = self.__watchFiles.pop(path) - if self.__monitor.get_path(wdInt) is not None: - wd = self.__monitor.rm_watch(wdInt) - else: # pragma: no cover + if not self._delWatch(wdInt): # pragma: no cover logSys.debug("Non-existing file watcher %r for file %s", wdInt, path) - wd = {wdInt: 1} - if wd[wdInt]: - logSys.debug("Removed file watcher for %s", path) - return True + logSys.debug("Removed file watcher for %s", path) + return True except KeyError: # pragma: no cover pass - # EnvironmentError is parent of IOError, OSError, etc. - except EnvironmentError as e: # pragma: no cover (normally unreached) - logSys.error("Remove file monitor for %s causes %s", path, e) return False def _addDirWatcher(self, path_dir): @@ -256,16 +261,11 @@ class FilterPyinotify(FileFilter): # Remove watches for the directory: try: wdInt = self.__watchDirs.pop(path_dir) - if self.__monitor.get_path(wdInt) is not None: - self.__monitor.rm_watch(wdInt) - else: # pragma: no cover + if not self._delWatch(wdInt): # pragma: no cover logSys.debug("Non-existing file watcher %r for directory %s", wdInt, path_dir) + logSys.debug("Removed monitor for the parent directory %s", path_dir) except KeyError: # pragma: no cover pass - # EnvironmentError is parent of IOError, OSError, etc. - except EnvironmentError as e: # pragma: no cover (normally unreached) - logSys.error("Remove monitor for the parent directory %s causes %s", path_dir, e) - logSys.debug("Removed monitor for the parent directory %s", path_dir) ## # Add a log file path diff --git a/fail2ban/tests/filtertestcase.py b/fail2ban/tests/filtertestcase.py index eb57c192..1803974b 100644 --- a/fail2ban/tests/filtertestcase.py +++ b/fail2ban/tests/filtertestcase.py @@ -980,6 +980,21 @@ def get_monitor_failures_testcase(Filter_): self.assert_correct_last_attempt(GetFailures.FAILURES_01) self.assertEqual(self.filter.failManager.getFailTotal(), 6) + def test_pyinotify_delWatch(self): + if hasattr(self.filter, '_delWatch'): # pyinotify only + m = self.filter._FilterPyinotify__monitor + # remove existing watch: + self.assertTrue(self.filter._delWatch(m.get_wd(self.name))) + # mockup get_path to allow once find path for invalid wd-value: + _org_get_path = m.get_path + def _get_path(wd): + #m.get_path = _org_get_path + return 'test' + m.get_path = _get_path + # try remove watch using definitely not existing handle: + self.assertFalse(self.filter._delWatch(0x7fffffff)) + m.get_path = _org_get_path + def test_del_file(self): # test filter reaction by delete watching file: self.file.close()