Merge branch '0.10' into 0.11

pull/2093/head
sebres 2018-03-02 21:42:07 +01:00
commit ccb1daf30a
4 changed files with 31 additions and 20 deletions

View File

@ -76,6 +76,10 @@ class RequestHandler(asynchat.async_chat):
#logSys.debug("Received raw data: " + str(data)) #logSys.debug("Received raw data: " + str(data))
self.__buffer.append(data) self.__buffer.append(data)
# exception identifies deserialization errors (exception by load in pickle):
class LoadError(Exception):
pass
## ##
# Handles a new request. # Handles a new request.
# #
@ -93,7 +97,12 @@ class RequestHandler(asynchat.async_chat):
self.close_when_done() self.close_when_done()
return return
# Deserialize # 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()<logging.DEBUG)
raise RequestHandler.LoadError(e)
# Gives the message to the transmitter. # Gives the message to the transmitter.
if self.__transmitter: if self.__transmitter:
message = self.__transmitter.proceed(message) message = self.__transmitter.proceed(message)
@ -104,8 +113,9 @@ class RequestHandler(asynchat.async_chat):
# Sends the response to the client. # Sends the response to the client.
self.push(message + CSPROTO.END) self.push(message + CSPROTO.END)
except Exception as e: except Exception as e:
logSys.error("Caught unhandled exception: %r", e, if not isinstance(e, RequestHandler.LoadError): # pragma: no cover - normally unreachable
exc_info=logSys.getEffectiveLevel()<=logging.DEBUG) logSys.error("Caught unhandled exception: %r", e,
exc_info=logSys.getEffectiveLevel()<=logging.DEBUG)
# Sends the response to the client. # Sends the response to the client.
message = dumps("ERROR: %s" % e, HIGHEST_PROTOCOL) message = dumps("ERROR: %s" % e, HIGHEST_PROTOCOL)
self.push(message + CSPROTO.END) self.push(message + CSPROTO.END)
@ -200,23 +210,21 @@ class AsyncServer(asyncore.dispatcher):
def handle_accept(self): def handle_accept(self):
try: try:
conn, addr = self.accept() conn, addr = self.accept()
except socket.error as e: # pragma: no cover except Exception as e: # pragma: no cover
self.__errCount['accept'] += 1 self.__errCount['accept'] += 1
if self.__errCount['accept'] < 20: if self.__errCount['accept'] < 20:
logSys.warning("Socket error: %s", e) logSys.warning("Accept socket error: %s", e,
exc_info=(self.__errCount['accept'] <= 1))
elif self.__errCount['accept'] == 20: elif self.__errCount['accept'] == 20:
logSys.error("Too many acceptor errors - stop logging errors") logSys.error("Too many acceptor errors - stop logging errors")
elif self.__errCount['accept'] > 100: elif self.__errCount['accept'] > 100:
if ( 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 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() self.stop()
return return
except TypeError as e: # pragma: no cover
logSys.warning("Type error: %s", e)
return
if self.__errCount['accept']: if self.__errCount['accept']:
self.__errCount['accept'] -= 1; self.__errCount['accept'] -= 1;
AsyncServer.__markCloseOnExec(conn) AsyncServer.__markCloseOnExec(conn)
@ -265,6 +273,13 @@ class AsyncServer(asyncore.dispatcher):
stopflg = False stopflg = False
if self.__active: if self.__active:
self.__loop = False 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) asyncore.dispatcher.close(self)
# If not the loop thread (stops self in handler), wait (a little bit) # If not the loop thread (stops self in handler), wait (a little bit)
# for the server leaves loop, before remove socket # for the server leaves loop, before remove socket
@ -284,14 +299,8 @@ class AsyncServer(asyncore.dispatcher):
def stop_communication(self): def stop_communication(self):
if self.__transmitter: if self.__transmitter:
logSys.debug("Stop communication") logSys.debug("Stop communication, shutdown")
self.__transmitter = None 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. # Stops the server.

View File

@ -102,7 +102,7 @@ class Utils():
def unset(self, k): def unset(self, k):
try: try:
del self._cache[k] del self._cache[k]
except KeyError: # pragma: no cover except KeyError:
pass pass

View File

@ -1640,6 +1640,8 @@ class DNSUtilsTests(unittest.TestCase):
c.set(i, i) c.set(i, i)
for i in xrange(5): for i in xrange(5):
self.assertEqual(c.get(i), i) self.assertEqual(c.get(i), i)
# remove unavailable key:
c.unset('a'); c.unset('a')
def testCacheMaxSize(self): def testCacheMaxSize(self):
c = Utils.Cache(maxCount=5, maxTime=60) c = Utils.Cache(maxCount=5, maxTime=60)

View File

@ -57,7 +57,7 @@ class Socket(LogCaptureTestCase):
LogCaptureTestCase.setUp(self) LogCaptureTestCase.setUp(self)
super(Socket, self).setUp() super(Socket, self).setUp()
self.server = AsyncServer(self) 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.close(sock_fd)
os.remove(sock_name) os.remove(sock_name)
self.sock_name = sock_name self.sock_name = sock_name
@ -120,7 +120,7 @@ class Socket(LogCaptureTestCase):
# test wrong message: # test wrong message:
self.assertEqual(client.send([[TestMsg()]]), 'ERROR: test unpickle error') 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: # test good message again:
self.assertEqual(client.send(testMessage), testMessage) self.assertEqual(client.send(testMessage), testMessage)