From f3dbc9dda10e52610e3de26f538b5581fd905505 Mon Sep 17 00:00:00 2001 From: sebres Date: Thu, 12 Dec 2019 21:28:16 +0100 Subject: [PATCH] set real thread names (used for identification and diagnostic purposes, e. g. top -H, ps -e -T, pstree, etc) --- fail2ban/helpers.py | 24 ++++++++++++++++++++++++ fail2ban/server/actions.py | 2 +- fail2ban/server/filter.py | 2 ++ fail2ban/server/jailthread.py | 15 +++++++++++++-- fail2ban/server/server.py | 4 +++- fail2ban/tests/filtertestcase.py | 2 +- 6 files changed, 44 insertions(+), 5 deletions(-) diff --git a/fail2ban/helpers.py b/fail2ban/helpers.py index c6da8f30..8d981ed6 100644 --- a/fail2ban/helpers.py +++ b/fail2ban/helpers.py @@ -32,6 +32,13 @@ from threading import Lock from .server.mytime import MyTime +try: + import ctypes + _libcap = ctypes.CDLL('libcap.so.2') +except: + _libcap = None + + PREFER_ENC = locale.getpreferredencoding() # correct preferred encoding if lang not set in environment: if PREFER_ENC.startswith('ANSI_'): # pragma: no cover @@ -451,6 +458,23 @@ def substituteRecursiveTags(inptags, conditional='', return tags +if _libcap: + def prctl_set_th_name(name): + """Helper to set real thread name (used for identification and diagnostic purposes). + """ + try: + if sys.version_info >= (3,): # pragma: 2.x no cover + name = name.encode() + else: # pragma: 3.x no cover + name = bytes(name) + _libcap.prctl(15, name[0:15]) # PR_SET_NAME = 15, name can be up to 15 bytes long (16 bytes with NTS zero) + except: + pass +else: # pragma: no cover + def prctl_set_th_name(name): + pass + + class BgService(object): """Background servicing diff --git a/fail2ban/server/actions.py b/fail2ban/server/actions.py index 1090fed0..51904ecd 100644 --- a/fail2ban/server/actions.py +++ b/fail2ban/server/actions.py @@ -75,7 +75,7 @@ class Actions(JailThread, Mapping): """ def __init__(self, jail): - JailThread.__init__(self) + JailThread.__init__(self, name="f2b/a."+jail.name) ## The jail which contains this action. self._jail = jail self._actions = OrderedDict() diff --git a/fail2ban/server/filter.py b/fail2ban/server/filter.py index 94342b31..98c28e35 100644 --- a/fail2ban/server/filter.py +++ b/fail2ban/server/filter.py @@ -109,6 +109,8 @@ class Filter(JailThread): self.checkFindTime = True ## Ticks counter self.ticks = 0 + ## Thread name: + self.name="f2b/f."+self.jailName self.dateDetector = DateDetector() logSys.debug("Created %s", self) diff --git a/fail2ban/server/jailthread.py b/fail2ban/server/jailthread.py index 5c7afd38..d0430367 100644 --- a/fail2ban/server/jailthread.py +++ b/fail2ban/server/jailthread.py @@ -29,7 +29,7 @@ from threading import Thread from abc import abstractmethod from .utils import Utils -from ..helpers import excepthook +from ..helpers import excepthook, prctl_set_th_name class JailThread(Thread): @@ -76,6 +76,15 @@ class JailThread(Thread): print(e) self.run = run_with_except_hook + if sys.version_info >= (3,): # pragma: 2.x no cover + def _bootstrap(self): + prctl_set_th_name(self.name) + return super(JailThread, self)._bootstrap(); + else: # pragma: 3.x no cover + def __bootstrap(self): + prctl_set_th_name(self.name) + return Thread._Thread__bootstrap(self) + @abstractmethod def status(self, flavor="basic"): # pragma: no cover - abstract """Abstract - Should provide status information. @@ -108,4 +117,6 @@ class JailThread(Thread): if self.active is not None: super(JailThread, self).join() - +## python 2.x replace binding of private __bootstrap method: +if sys.version_info < (3,): # pragma: 3.x no cover + JailThread._Thread__bootstrap = JailThread._JailThread__bootstrap diff --git a/fail2ban/server/server.py b/fail2ban/server/server.py index 35f966e8..7c820e49 100644 --- a/fail2ban/server/server.py +++ b/fail2ban/server/server.py @@ -38,7 +38,7 @@ from .transmitter import Transmitter from .asyncserver import AsyncServer, AsyncServerException from .. import version from ..helpers import getLogger, _as_bool, extractOptions, str2LogLevel, \ - getVerbosityFormat, excepthook + getVerbosityFormat, excepthook, prctl_set_th_name # Gets the instance of the logger. logSys = getLogger(__name__) @@ -80,6 +80,8 @@ class Server: 'Linux': '/dev/log', } self.__prev_signals = {} + # replace real thread name with short process name (for top/ps/pstree or diagnostic): + prctl_set_th_name('f2b/server') def __sigTERMhandler(self, signum, frame): # pragma: no cover - indirect tested logSys.debug("Caught signal %d. Exiting", signum) diff --git a/fail2ban/tests/filtertestcase.py b/fail2ban/tests/filtertestcase.py index 38d77d0b..41a6f0bf 100644 --- a/fail2ban/tests/filtertestcase.py +++ b/fail2ban/tests/filtertestcase.py @@ -266,7 +266,7 @@ class BasicFilter(unittest.TestCase): def setUp(self): super(BasicFilter, self).setUp() - self.filter = Filter('name') + self.filter = Filter(None) def testGetSetUseDNS(self): # default is warn