From 07689f87cb6fcd1d267b39df7e7f29a05a91b144 Mon Sep 17 00:00:00 2001 From: XANTRONIX Development Date: Tue, 3 Dec 2024 16:53:31 -0500 Subject: [PATCH] Implement PID file support in nntp.tiny.daemon --- bin/nntp-tiny-server | 6 ++---- lib/nntp/tiny/config.py | 32 ++++++++++++++++++++++++++++---- lib/nntp/tiny/daemon.py | 26 ++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 8 deletions(-) create mode 100644 lib/nntp/tiny/daemon.py diff --git a/bin/nntp-tiny-server b/bin/nntp-tiny-server index 590f8e5..0f394ae 100755 --- a/bin/nntp-tiny-server +++ b/bin/nntp-tiny-server @@ -6,6 +6,7 @@ import argparse from nntp.tiny.config import Config from nntp.tiny.db import Database from nntp.tiny.server import Server +from nntp.tiny.daemon import Daemon parser = argparse.ArgumentParser(description='Tiny NNTP server') parser.add_argument('--daemon', '-d', action='store_true', help='Run NNTP server as daemon in background') @@ -16,9 +17,6 @@ config = Config.load() server = Server(config) if args.daemon: - pid = os.fork() - - if pid > 0: - exit(0) + Daemon.init(config) server.run() diff --git a/lib/nntp/tiny/config.py b/lib/nntp/tiny/config.py index ba27afd..5058252 100644 --- a/lib/nntp/tiny/config.py +++ b/lib/nntp/tiny/config.py @@ -4,11 +4,35 @@ import configparser from typing import Optional class ConfigException(Exception): - def __init__(self, path: str): - self.path = path + pass + +class ConfigSectionException(ConfigException): + def __init__(self, section: str): + self.section = section def __str__(self): - return "Unable to locate file '" + self.path + "'" + return "Missing configuration section '%s'" % ( + self.section + ) + +class ConfigValueException(ConfigException): + def __init__(self, section: str, value: str): + self.section = section + self.value = value + + def __str__(self): + return "Missing configuration value '%s' in section '%s'" % ( + self.value, self.section + ) + +class ConfigFileException(ConfigException): + def __init__(self, paths: list): + self.paths = paths + + def __str__(self): + return "Unable to locate configuration file in: %s" % ( + ", ".join(self.paths) + ) class Config(): SEARCH_PATHS = [ @@ -29,7 +53,7 @@ class Config(): path = Config.find() if path is None: - raise ConfigException(path) + raise ConfigFileException(Config.SEARCH_PATHS) parser = configparser.ConfigParser() parser.read(path) diff --git a/lib/nntp/tiny/daemon.py b/lib/nntp/tiny/daemon.py new file mode 100644 index 0000000..72b7c07 --- /dev/null +++ b/lib/nntp/tiny/daemon.py @@ -0,0 +1,26 @@ +import os +import signal +import configparser + +from nntp.tiny.config import (ConfigSectionException, + ConfigValueException) + +class Daemon(): + def init(config: configparser.ConfigParser): + if not config.has_section('daemon'): + raise ConfigSectionException('daemon') + + if not config.has_option('daemon', 'pidfile'): + raise ConfigValueException('daemon', 'pidfile') + + pidfile = config.get('daemon', 'pidfile') + + pid = os.fork() + + if pid > 0: + exit(0) + + with open(pidfile, 'w') as fh: + print(str(os.getpid()), file=fh) + + signal.signal(signal.SIGTERM, lambda s, f: os.unlink(pidfile))