diff --git a/fail2ban/server/asyncserver.py b/fail2ban/server/asyncserver.py index eb99c69a..e3400737 100644 --- a/fail2ban/server/asyncserver.py +++ b/fail2ban/server/asyncserver.py @@ -76,6 +76,10 @@ class RequestHandler(asynchat.async_chat): #logSys.debug("Received raw data: " + str(data)) self.__buffer.append(data) + # exception identifies deserialization errors (exception by load in pickle): + class LoadError(Exception): + pass + ## # Handles a new request. # @@ -93,7 +97,12 @@ class RequestHandler(asynchat.async_chat): self.close_when_done() return # Deserialize - message = loads(message) + try: + message = loads(message) + except Exception as e: + logSys.error('PROTO-error: load message failed: %s', e, + exc_info=logSys.getEffectiveLevel() 100: if ( - e.args[0] == errno.EMFILE # [Errno 24] Too many open files + (isinstance(e, socket.error) and e.args[0] == errno.EMFILE) # [Errno 24] Too many open files or sum(self.__errCount.itervalues()) > 1000 ): - logSys.critical("Too many errors - critical count reached %r", err_count) + logSys.critical("Too many errors - critical count reached %r", self.__errCount) self.stop() return - except TypeError as e: # pragma: no cover - logSys.warning("Type error: %s", e) - return if self.__errCount['accept']: self.__errCount['accept'] -= 1; AsyncServer.__markCloseOnExec(conn) @@ -265,6 +273,13 @@ class AsyncServer(asyncore.dispatcher): stopflg = False if self.__active: self.__loop = False + # shutdown socket here: + if self.socket: + try: + self.socket.shutdown(socket.SHUT_RDWR) + except socket.error: # pragma: no cover - normally unreachable + pass + # close connection: asyncore.dispatcher.close(self) # If not the loop thread (stops self in handler), wait (a little bit) # for the server leaves loop, before remove socket @@ -284,14 +299,8 @@ class AsyncServer(asyncore.dispatcher): def stop_communication(self): if self.__transmitter: - logSys.debug("Stop communication") + logSys.debug("Stop communication, shutdown") self.__transmitter = None - # shutdown socket here: - if self.socket: - try: - self.socket.shutdown(socket.SHUT_RDWR) - except socket.error: # pragma: no cover - normally unreachable - pass ## # Stops the server. diff --git a/fail2ban/server/utils.py b/fail2ban/server/utils.py index 613f623d..b59fb4e1 100644 --- a/fail2ban/server/utils.py +++ b/fail2ban/server/utils.py @@ -102,7 +102,7 @@ class Utils(): def unset(self, k): try: del self._cache[k] - except KeyError: # pragma: no cover + except KeyError: pass diff --git a/fail2ban/tests/filtertestcase.py b/fail2ban/tests/filtertestcase.py index b5877b7f..2bbfcd9d 100644 --- a/fail2ban/tests/filtertestcase.py +++ b/fail2ban/tests/filtertestcase.py @@ -1640,6 +1640,8 @@ class DNSUtilsTests(unittest.TestCase): c.set(i, i) for i in xrange(5): self.assertEqual(c.get(i), i) + # remove unavailable key: + c.unset('a'); c.unset('a') def testCacheMaxSize(self): c = Utils.Cache(maxCount=5, maxTime=60) diff --git a/fail2ban/tests/sockettestcase.py b/fail2ban/tests/sockettestcase.py index a7c3a43c..69bf8d8b 100644 --- a/fail2ban/tests/sockettestcase.py +++ b/fail2ban/tests/sockettestcase.py @@ -57,7 +57,7 @@ class Socket(LogCaptureTestCase): LogCaptureTestCase.setUp(self) super(Socket, self).setUp() self.server = AsyncServer(self) - sock_fd, sock_name = tempfile.mkstemp('fail2ban.sock', 'socket') + sock_fd, sock_name = tempfile.mkstemp('fail2ban.sock', 'f2b-socket') os.close(sock_fd) os.remove(sock_name) self.sock_name = sock_name @@ -120,7 +120,7 @@ class Socket(LogCaptureTestCase): # test wrong message: self.assertEqual(client.send([[TestMsg()]]), 'ERROR: test unpickle error') - self.assertLogged("Caught unhandled exception", "test unpickle error", all=True) + self.assertLogged("PROTO-error: load message failed:", "test unpickle error", all=True) # test good message again: self.assertEqual(client.send(testMessage), testMessage)