diff --git a/ospd/main.py b/ospd/main.py index e1f498ec..69535206 100644 --- a/ospd/main.py +++ b/ospd/main.py @@ -22,10 +22,14 @@ import os import sys +import atexit +import signal + +from functools import partial from typing import Type, Optional -from ospd.misc import go_to_background +from ospd.misc import go_to_background, create_pid, remove_pidfile from ospd.ospd import OSPDaemon from ospd.parser import create_parser, ParserType from ospd.server import TlsServer, UnixSocketServer @@ -128,11 +132,20 @@ def main( print_version(daemon) sys.exit() - daemon.init() - if not args.foreground: go_to_background() + if not create_pid(args.pid_file): + sys.exit() + + # Set signal handler and cleanup + atexit.register(remove_pidfile, pidfile=args.pid_file) + signal.signal( + signal.SIGTERM, partial(remove_pidfile, args.pid_file) + ) + + daemon.init() + if not daemon.check(): return 1 diff --git a/ospd/misc.py b/ospd/misc.py index 10f501d3..9157a50b 100644 --- a/ospd/misc.py +++ b/ospd/misc.py @@ -30,6 +30,7 @@ from enum import Enum from collections import OrderedDict +from pathlib import Path from ospd.network import target_str_to_list @@ -408,3 +409,31 @@ def go_to_background(): except OSError as errmsg: LOGGER.error('Fork failed: %s', errmsg) sys.exit(1) + +def create_pid(pidfile): + """ Check if there is an already running daemon and creates the pid file. + Otherwise gives an error. """ + + pid = str(os.getpid()) + + if Path(pidfile).is_file(): + LOGGER.error("There is an already running process.") + return False + + try: + with open(pidfile, 'w') as f: + f.write(pid) + except (FileNotFoundError, PermissionError) as e: + msg = "Failed to create pid file %s. %s" % (os.path.dirname(pidfile), e) + LOGGER.error(msg) + return False + + return True + +def remove_pidfile(pidfile, signum=None, frame=None): + """ Removes the pidfile before ending the daemon. """ + pidpath = Path(pidfile) + if pidpath.is_file(): + LOGGER.debug("Finishing daemon process") + pidpath.unlink() + sys.exit() diff --git a/ospd/parser.py b/ospd/parser.py index f6bf197e..b607705d 100644 --- a/ospd/parser.py +++ b/ospd/parser.py @@ -33,6 +33,7 @@ DEFAULT_UNIX_SOCKET_MODE = "0o700" DEFAULT_CONFIG_PATH = "~/.config/ospd.conf" DEFAULT_UNIX_SOCKET_PATH = "/tmp/ospd.sock" +DEFAULT_PID_PATH = "/run/ospd/ospd.pid" ParserType = argparse.ArgumentParser Arguments = argparse.Namespace @@ -78,6 +79,11 @@ def __init__(self, description): default=DEFAULT_UNIX_SOCKET_PATH, help='Unix file socket to listen on. Default: %(default)s', ) + parser.add_argument( + '--pid-file', + default=DEFAULT_PID_PATH, + help='Unix file socket to listen on.' + ) parser.add_argument( '-m',