ENH: Log unhandled exceptions to Fail2Ban log

pull/701/head
Steven Hiscocks 11 years ago
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…
Cancel
Save