mirror of https://github.com/fail2ban/fail2ban
ENH: Log unhandled exceptions to Fail2Ban log
parent
e8131475cd
commit
f7da091437
|
@ -40,6 +40,7 @@ ver. 0.9.1 (2014/xx/xx) - better, faster, stronger
|
|||
* Match non "Bye Bye" disconnect messages for sshd locked account regex
|
||||
* Realign fail2ban log output with white space to improve readability. Does
|
||||
not affect SYSLOG output.
|
||||
* Log unhandled exceptions
|
||||
|
||||
ver. 0.9.0 (2014/03/14) - beta
|
||||
----------
|
||||
|
|
|
@ -112,3 +112,10 @@ def getF2BLogger(name):
|
|||
"""Get logging.Logger instance with Fail2Ban logger name convention
|
||||
"""
|
||||
return logging.getLogger("fail2ban.%s" % name.rpartition(".")[-1])
|
||||
|
||||
def fail2ban_excepthook(exctype, value, traceback):
|
||||
"""Except hook used to log unhandled exceptions to Fail2Ban log
|
||||
"""
|
||||
logging.getLogger("fail2ban").critical(
|
||||
"Unhandled exception in Fail2Ban:", exc_info=True)
|
||||
return sys.__excepthook__(exctype, value, traceback)
|
||||
|
|
|
@ -24,9 +24,12 @@ __author__ = "Cyril Jaquier"
|
|||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
import sys
|
||||
from threading import Thread
|
||||
from abc import abstractproperty, abstractmethod
|
||||
|
||||
from ..helpers import fail2ban_excepthook
|
||||
|
||||
class JailThread(Thread):
|
||||
"""Abstract class for threading elements in Fail2Ban.
|
||||
|
||||
|
@ -53,6 +56,16 @@ class JailThread(Thread):
|
|||
## The time the thread sleeps in the loop.
|
||||
self.sleeptime = 1
|
||||
|
||||
# excepthook workaround for threads, derived from:
|
||||
# http://bugs.python.org/issue1230540#msg91244
|
||||
run = self.run
|
||||
def run_with_except_hook(*args, **kwargs):
|
||||
try:
|
||||
run(*args, **kwargs)
|
||||
except:
|
||||
fail2ban_excepthook(*sys.exc_info())
|
||||
self.run = run_with_except_hook
|
||||
|
||||
@abstractproperty
|
||||
def status(self): # pragma: no cover - abstract
|
||||
"""Abstract - Should provide status information.
|
||||
|
|
|
@ -32,7 +32,7 @@ from .filter import FileFilter, JournalFilter
|
|||
from .transmitter import Transmitter
|
||||
from .asyncserver import AsyncServer, AsyncServerException
|
||||
from .. import version
|
||||
from ..helpers import getF2BLogger
|
||||
from ..helpers import getF2BLogger, fail2ban_excepthook
|
||||
|
||||
# Gets the instance of the logger.
|
||||
logSys = getF2BLogger(__name__)
|
||||
|
@ -70,6 +70,9 @@ class Server:
|
|||
signal.signal(signal.SIGTERM, self.__sigTERMhandler)
|
||||
signal.signal(signal.SIGINT, self.__sigTERMhandler)
|
||||
|
||||
# Ensure unhandled exceptions are logged
|
||||
sys.excepthook = fail2ban_excepthook
|
||||
|
||||
# First set the mask to only allow access to owner
|
||||
os.umask(0077)
|
||||
if self.__daemon: # pragma: no cover
|
||||
|
|
|
@ -35,6 +35,8 @@ import logging
|
|||
from ..server.failregex import Regex, FailRegex, RegexException
|
||||
from ..server.server import Server
|
||||
from ..server.jail import Jail
|
||||
from ..server.jailthread import JailThread
|
||||
from .utils import LogCaptureTestCase
|
||||
from ..helpers import getF2BLogger
|
||||
|
||||
try:
|
||||
|
@ -797,10 +799,19 @@ class RegexTests(unittest.TestCase):
|
|||
self.assertTrue(fr.hasMatched())
|
||||
self.assertRaises(RegexException, fr.getHost)
|
||||
|
||||
class LoggingTests(unittest.TestCase):
|
||||
class _BadThread(JailThread):
|
||||
def run(self):
|
||||
int("cat")
|
||||
|
||||
class LoggingTests(LogCaptureTestCase):
|
||||
|
||||
def testGetF2BLogger(self):
|
||||
testLogSys = getF2BLogger("fail2ban.some.string.with.name")
|
||||
self.assertEqual(testLogSys.parent.name, "fail2ban")
|
||||
self.assertEqual(testLogSys.name, "fail2ban.name")
|
||||
|
||||
def testFail2BanExceptHook(self):
|
||||
badThread = _BadThread()
|
||||
badThread.start()
|
||||
badThread.join()
|
||||
self.assertTrue(self._is_logged("Unhandled exception"))
|
||||
|
|
Loading…
Reference in New Issue