import os
import sys
import time
import signal
import multiprocessing


def print_signal(signum):
    def new_handler(signum, frame):
        nonlocal old_handler
        pid = os.getpid()
        print(f"[PID {pid}] SIGNAL {signum}", flush=True)
        if old_handler is None:
            old_handler = signal.SIG_IGN
        signal.signal(signum, old_handler)
        os.kill(pid, signum)

    try:
        old_handler = signal.signal(signum, new_handler)
    except (OSError, AttributeError, ValueError, RuntimeError):
        pass


def reg_signals():
    print_signal(signal.SIGINT)
    print_signal(signal.SIGTERM)
    print_signal(signal.SIGHUP)


def main(sleep_time):
    reg_signals()
    p = multiprocessing.current_process()
    s = "daemonic" if p.daemon else "non-daemonic"
    print("[Parent] Starting:", p.name, p.pid, s, flush=True)
    try:
        time.sleep(sleep_time)
    except BaseException as e:
        print("[Parent] Exception :", str(e), s, flush=True)
        raise
    else:
        print("[Parent] Finished normally:", p.name, p.pid, s, flush=True)
    finally:
        print("[Parent] Exiting :", p.name, p.pid, s, flush=True)
        sys.stdout.flush()


if __name__ == "__main__":
    d = multiprocessing.Process(name="daemon", target=main, args=(10,))
    d.daemon = True

    n = multiprocessing.Process(name="non-daemon", target=main, args=(15,))
    n.daemon = False

    d.start()
    n.start()

    time.sleep(2)

    print(f"[Parent] Send SIGTERM to daemon {d.pid} and wait for non-daemon {n.pid}")
