mirror of https://github.com/fail2ban/fail2ban
fix sporadic time related errors after fail2ban restart resp. reload jail:
- ValueError: need more than N values to unpack - empty banip from restoreCurrentBans, etc.pull/1460/head
parent
0636b3247d
commit
8c54675750
|
@ -80,7 +80,10 @@ class RequestHandler(asynchat.async_chat):
|
|||
# Deserialize
|
||||
message = loads(message)
|
||||
# Gives the message to the transmitter.
|
||||
if self.__transmitter:
|
||||
message = self.__transmitter.proceed(message)
|
||||
else:
|
||||
message = ['SHUTDOWN']
|
||||
# Serializes the response.
|
||||
message = dumps(message, HIGHEST_PROTOCOL)
|
||||
# Sends the response to the client.
|
||||
|
@ -228,6 +231,13 @@ class AsyncServer(asyncore.dispatcher):
|
|||
##
|
||||
# Stops the communication server.
|
||||
|
||||
def stop_communication(self):
|
||||
logSys.debug("Stop communication")
|
||||
self.__transmitter = None
|
||||
|
||||
##
|
||||
# Stops the server.
|
||||
|
||||
def stop(self):
|
||||
self.close()
|
||||
|
||||
|
|
|
@ -643,7 +643,6 @@ class Fail2BanDb(object):
|
|||
cur = self._db.cursor()
|
||||
return cur.execute(query, queryArgs)
|
||||
|
||||
@commitandrollback
|
||||
def _getCurrentBans(self, cur, jail = None, ip = None, forbantime=None, fromtime=None):
|
||||
if fromtime is None:
|
||||
fromtime = MyTime.time()
|
||||
|
@ -666,14 +665,23 @@ class Fail2BanDb(object):
|
|||
cur = self._db.cursor()
|
||||
return cur.execute(query, queryArgs)
|
||||
|
||||
def getCurrentBans(self, jail = None, ip = None, forbantime=None, fromtime=None):
|
||||
@commitandrollback
|
||||
def getCurrentBans(self, cur, jail = None, ip = None, forbantime=None, fromtime=None):
|
||||
tickets = []
|
||||
ticket = None
|
||||
|
||||
results = list(self._getCurrentBans(jail=jail, ip=ip, forbantime=forbantime, fromtime=fromtime))
|
||||
|
||||
if results:
|
||||
for banip, timeofban, bantime, bancount, data in results:
|
||||
for ticket in self._getCurrentBans(cur, jail=jail, ip=ip,
|
||||
forbantime=forbantime, fromtime=fromtime
|
||||
):
|
||||
# can produce unpack error (database may return sporadical wrong-empty row):
|
||||
try:
|
||||
banip, timeofban, bantime, bancount, data = ticket
|
||||
# additionally check for empty values:
|
||||
if banip is None or banip == "": # pragma: no cover
|
||||
raise ValueError('unexpected value %r' % (banip,))
|
||||
except ValueError as e: # pragma: no cover
|
||||
logSys.debug("get current bans: ignore row %r - %s", ticket, e)
|
||||
continue
|
||||
# logSys.debug('restore ticket %r, %r, %r', banip, timeofban, data)
|
||||
ticket = FailTicket(banip, timeofban, data=data)
|
||||
# logSys.debug('restored ticket: %r', ticket)
|
||||
|
|
|
@ -274,8 +274,9 @@ class Jail(object):
|
|||
if not self.getBanTimeExtra('increment'):
|
||||
forbantime = self.actions.getBanTime()
|
||||
for ticket in self.database.getCurrentBans(jail=self, forbantime=forbantime):
|
||||
try:
|
||||
#logSys.debug('restored ticket: %s', ticket)
|
||||
if not self.filter.inIgnoreIPList(ticket.getIP(), log_ignore=True):
|
||||
if self.filter.inIgnoreIPList(ticket.getIP(), log_ignore=True): continue
|
||||
# mark ticked was restored from database - does not put it again into db:
|
||||
ticket.restored = True
|
||||
# correct start time / ban time (by the same end of ban):
|
||||
|
@ -288,7 +289,11 @@ class Jail(object):
|
|||
continue
|
||||
self.putFailTicket(ticket)
|
||||
except Exception as e: # pragma: no cover
|
||||
logSys.error('%s', e, exc_info=logSys.getEffectiveLevel()<=logging.DEBUG)
|
||||
logSys.error('Restore ticket failed: %s', e,
|
||||
exc_info=logSys.getEffectiveLevel()<=logging.DEBUG)
|
||||
except Exception as e: # pragma: no cover
|
||||
logSys.error('Restore bans failed: %s', e,
|
||||
exc_info=logSys.getEffectiveLevel()<=logging.DEBUG)
|
||||
|
||||
def start(self):
|
||||
"""Start the jail, by starting filter and actions threads.
|
||||
|
|
|
@ -159,17 +159,16 @@ class Server:
|
|||
self.__asyncServer.start(sock, force)
|
||||
except AsyncServerException as e:
|
||||
logSys.error("Could not start server: %s", e)
|
||||
|
||||
# Removes the PID file.
|
||||
try:
|
||||
logSys.debug("Remove PID file %s", pidfile)
|
||||
os.remove(pidfile)
|
||||
except (OSError, IOError) as e: # pragma: no cover
|
||||
logSys.error("Unable to remove PID file: %s", e)
|
||||
# Stop observer and exit
|
||||
if Observers.Main is not None:
|
||||
Observers.Main.stop()
|
||||
Observers.Main = None
|
||||
logSys.info("Exiting Fail2ban")
|
||||
|
||||
# Stop (if not yet already executed):
|
||||
self.quit()
|
||||
|
||||
def quit(self):
|
||||
# Give observer a small chance to complete its work before exit
|
||||
|
@ -183,8 +182,7 @@ class Server:
|
|||
# are exiting)
|
||||
# See https://github.com/fail2ban/fail2ban/issues/7
|
||||
if self.__asyncServer is not None:
|
||||
self.__asyncServer.stop()
|
||||
self.__asyncServer = None
|
||||
self.__asyncServer.stop_communication()
|
||||
|
||||
# Now stop all the jails
|
||||
self.stopAllJail()
|
||||
|
@ -205,6 +203,16 @@ class Server:
|
|||
for s, sh in self.__prev_signals.iteritems():
|
||||
signal.signal(s, sh)
|
||||
|
||||
# Stop observer and exit
|
||||
if Observers.Main is not None:
|
||||
Observers.Main.stop()
|
||||
Observers.Main = None
|
||||
# Stop async
|
||||
if self.__asyncServer is not None:
|
||||
self.__asyncServer.stop()
|
||||
self.__asyncServer = None
|
||||
logSys.info("Exiting Fail2ban")
|
||||
|
||||
# Prevent to call quit twice:
|
||||
self.quit = lambda: False
|
||||
|
||||
|
|
Loading…
Reference in New Issue