mirror of https://github.com/fail2ban/fail2ban
amend to #1778: repair notifier wait-cycle (too long timeout in polling, too late check for pending files, too long stop)
parent
050076ae42
commit
96c3b06abb
|
@ -82,7 +82,7 @@ class FilterPyinotify(FileFilter):
|
||||||
self.__watchDirs = dict()
|
self.__watchDirs = dict()
|
||||||
self.__pending = dict()
|
self.__pending = dict()
|
||||||
self.__pendingChkTime = 0
|
self.__pendingChkTime = 0
|
||||||
self.__pendingNextTime = 0
|
self.__pendingMinTime = 60
|
||||||
logSys.debug("Created FilterPyinotify")
|
logSys.debug("Created FilterPyinotify")
|
||||||
|
|
||||||
def callback(self, event, origin=''):
|
def callback(self, event, origin=''):
|
||||||
|
@ -150,7 +150,7 @@ class FilterPyinotify(FileFilter):
|
||||||
def _addPending(self, path, reason, isDir=False):
|
def _addPending(self, path, reason, isDir=False):
|
||||||
if path not in self.__pending:
|
if path not in self.__pending:
|
||||||
self.__pending[path] = [Utils.DEFAULT_SLEEP_INTERVAL, isDir];
|
self.__pending[path] = [Utils.DEFAULT_SLEEP_INTERVAL, isDir];
|
||||||
self.__pendingNextTime = 0
|
self.__pendingMinTime = 0
|
||||||
if isinstance(reason, pyinotify.Event):
|
if isinstance(reason, pyinotify.Event):
|
||||||
reason = [reason.maskname, reason.pathname]
|
reason = [reason.maskname, reason.pathname]
|
||||||
logSys.log(logging.MSG, "Log absence detected (possibly rotation) for %s, reason: %s of %s",
|
logSys.log(logging.MSG, "Log absence detected (possibly rotation) for %s, reason: %s of %s",
|
||||||
|
@ -165,7 +165,7 @@ class FilterPyinotify(FileFilter):
|
||||||
if not self.__pending:
|
if not self.__pending:
|
||||||
return
|
return
|
||||||
ntm = time.time()
|
ntm = time.time()
|
||||||
if ntm < self.__pendingNextTime:
|
if ntm < self.__pendingChkTime + self.__pendingMinTime:
|
||||||
return
|
return
|
||||||
found = {}
|
found = {}
|
||||||
minTime = 60
|
minTime = 60
|
||||||
|
@ -187,7 +187,7 @@ class FilterPyinotify(FileFilter):
|
||||||
del self.__pending[path]
|
del self.__pending[path]
|
||||||
except KeyError: pass
|
except KeyError: pass
|
||||||
self.__pendingChkTime = time.time()
|
self.__pendingChkTime = time.time()
|
||||||
self.__pendingNextTime = self.__pendingChkTime + minTime
|
self.__pendingMinTime = minTime
|
||||||
# process now because we've missed it in monitoring:
|
# process now because we've missed it in monitoring:
|
||||||
for path, isDir in found.iteritems():
|
for path, isDir in found.iteritems():
|
||||||
# refresh monitoring of this:
|
# refresh monitoring of this:
|
||||||
|
@ -295,6 +295,12 @@ class FilterPyinotify(FileFilter):
|
||||||
self.commonError()
|
self.commonError()
|
||||||
self.ticks += 1
|
self.ticks += 1
|
||||||
|
|
||||||
|
@property
|
||||||
|
def __notify_maxtout(self):
|
||||||
|
# timeout for pyinotify must be set in milliseconds (fail2ban time values are
|
||||||
|
# floats contain seconds), max 0.5 sec (additionally regards pending check time)
|
||||||
|
return min(self.sleeptime, 0.5, self.__pendingMinTime) * 1000
|
||||||
|
|
||||||
##
|
##
|
||||||
# Main loop.
|
# Main loop.
|
||||||
#
|
#
|
||||||
|
@ -304,9 +310,8 @@ class FilterPyinotify(FileFilter):
|
||||||
def run(self):
|
def run(self):
|
||||||
prcevent = pyinotify.ProcessEvent()
|
prcevent = pyinotify.ProcessEvent()
|
||||||
prcevent.process_default = self.__process_default
|
prcevent.process_default = self.__process_default
|
||||||
## timeout for pyinotify must be set in milliseconds (our time values are floats contain seconds)
|
|
||||||
self.__notifier = pyinotify.Notifier(self.__monitor,
|
self.__notifier = pyinotify.Notifier(self.__monitor,
|
||||||
prcevent, timeout=self.sleeptime * 1000)
|
prcevent, timeout=self.__notify_maxtout)
|
||||||
logSys.debug("[%s] filter started (pyinotifier)", self.jailName)
|
logSys.debug("[%s] filter started (pyinotifier)", self.jailName)
|
||||||
while self.active:
|
while self.active:
|
||||||
try:
|
try:
|
||||||
|
@ -314,13 +319,19 @@ class FilterPyinotify(FileFilter):
|
||||||
# slow check events while idle:
|
# slow check events while idle:
|
||||||
if self.idle:
|
if self.idle:
|
||||||
if Utils.wait_for(lambda: not self.active or not self.idle,
|
if Utils.wait_for(lambda: not self.active or not self.idle,
|
||||||
self.sleeptime * 10, self.sleeptime
|
min(self.sleeptime * 10, self.__pendingMinTime),
|
||||||
|
min(self.sleeptime, self.__pendingMinTime)
|
||||||
):
|
):
|
||||||
if not self.active: break
|
if not self.active: break
|
||||||
|
|
||||||
# default pyinotify handling using Notifier:
|
# default pyinotify handling using Notifier:
|
||||||
self.__notifier.process_events()
|
self.__notifier.process_events()
|
||||||
if Utils.wait_for(lambda: not self.active or self.__notifier.check_events(), self.sleeptime):
|
|
||||||
|
# wait for events / timeout:
|
||||||
|
notify_maxtout = self.__notify_maxtout
|
||||||
|
def __check_events():
|
||||||
|
return not self.active or self.__notifier.check_events(timeout=notify_maxtout)
|
||||||
|
if Utils.wait_for(__check_events, min(self.sleeptime, self.__pendingMinTime)):
|
||||||
if not self.active: break
|
if not self.active: break
|
||||||
self.__notifier.read_events()
|
self.__notifier.read_events()
|
||||||
|
|
||||||
|
@ -347,11 +358,10 @@ class FilterPyinotify(FileFilter):
|
||||||
# Call super.stop() and then stop the 'Notifier'
|
# Call super.stop() and then stop the 'Notifier'
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
if self.__notifier: # stop the notifier
|
|
||||||
self.__notifier.stop()
|
|
||||||
# stop filter thread:
|
# stop filter thread:
|
||||||
super(FilterPyinotify, self).stop()
|
super(FilterPyinotify, self).stop()
|
||||||
self.join()
|
if self.__notifier: # stop the notifier
|
||||||
|
self.__notifier.stop()
|
||||||
|
|
||||||
##
|
##
|
||||||
# Wait for exit with cleanup.
|
# Wait for exit with cleanup.
|
||||||
|
|
|
@ -996,6 +996,7 @@ def get_monitor_failures_testcase(Filter_):
|
||||||
self._wait4failures(2)
|
self._wait4failures(2)
|
||||||
# stop before tmpdir deleted (just prevents many monitor events)
|
# stop before tmpdir deleted (just prevents many monitor events)
|
||||||
self.filter.stop()
|
self.filter.stop()
|
||||||
|
self.filter.join()
|
||||||
|
|
||||||
|
|
||||||
def _test_move_into_file(self, interim_kill=False):
|
def _test_move_into_file(self, interim_kill=False):
|
||||||
|
|
Loading…
Reference in New Issue