diff options
Diffstat (limited to 'subplot/daemon.py')
-rw-r--r-- | subplot/daemon.py | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/subplot/daemon.py b/subplot/daemon.py new file mode 100644 index 0000000..e223505 --- /dev/null +++ b/subplot/daemon.py @@ -0,0 +1,84 @@ +############################################################################# +# Start and stop daemons, or background processes. + + +import logging +import os +import signal +import time + + +# Start a process in the background. +def start_daemon(ctx, name, argv): + runcmd = globals()["runcmd"] + exit_code_is = globals()["exit_code_is"] + + logging.debug(f"Starting daemon {name}") + logging.debug(f" ctx={ctx.as_dict()}") + logging.debug(f" name={name}") + logging.debug(f" argv={argv}") + + if "daemon" not in ctx.as_dict(): + ctx["daemon"] = {} + assert name not in ctx["daemon"] + this = ctx["daemon"][name] = { + "pid-file": f"{name}.pid", + "stderr": f"{name}.stderr", + "stdout": f"{name}.stdout", + } + runcmd( + ctx, + [ + "/usr/sbin/daemonize", + "-c", + os.getcwd(), + "-p", + this["pid-file"], + "-e", + this["stderr"], + "-o", + this["stdout"], + ] + + argv, + ) + + # Wait for a bit for daemon to start and maybe find a problem and die. + time.sleep(3) + if ctx["exit"] != 0: + logging.error(f"obnam-server stderr: {ctx['stderr']}") + + exit_code_is(ctx, 0) + this["pid"] = int(open(this["pid-file"]).read().strip()) + assert process_exists(this["pid"]) + + logging.debug(f"Started daemon {name}") + logging.debug(f" ctx={ctx.as_dict()}") + + +# Stop a daemon. +def stop_daemon(ctx, name): + logging.debug(f"Stopping daemon {name}") + logging.debug(f" ctx={ctx.as_dict()}") + logging.debug(f" ctx['daemon']={ctx.as_dict()['daemon']}") + + this = ctx["daemon"][name] + terminate_process(this["pid"], signal.SIGKILL) + + +# Does a process exist? +def process_exists(pid): + try: + os.kill(pid, 0) + except ProcessLookupError: + return False + return True + + +# Terminate process. +def terminate_process(pid, signalno): + logging.debug(f"Terminating process {pid} with signal {signalno}") + try: + os.kill(pid, signalno) + except ProcessLookupError: + logging.debug("Process did not actually exist (anymore?)") + pass |