HEX
Server: Apache
System: Linux nc-ph-0707-26.instaforreviews.com 3.10.0-1160.119.1.el7.tuxcare.els13.x86_64 #1 SMP Fri Nov 22 06:29:45 UTC 2024 x86_64
User: qirgxuo4hkuv (1004)
PHP: 8.3.27
Disabled: NONE
Upload Files
File: //proc/16903/cwd/sbin/wafd_imunify_daemon.bin
#!/opt/imunify360/venv/bin/python3
from contextlib import suppress
import gc
from pathlib import Path
import signal
import subprocess
import sys
import time

import psutil
from wafd_i360.internals import getLogger, logger_init

MAX_FAILURES_PER_HOUR = 10

TRANSIENT_SIGLIST =(signal.SIGABRT,
                    signal.SIGCONT,
                    signal.SIGHUP,
                    signal.SIGINT,
                    signal.SIGPIPE,
                    signal.SIGQUIT,
                    signal.SIGUSR1,
                    signal.SIGUSR2,
                    signal.SIGTERM)

PIDFILE = Path('/var/run/wafd_imunify_daemon-watchdog.pid')

logger = getLogger()


def wire_signals(reroute_to: subprocess.Popen=None, undo=False):
    def child_proc_send(sig, _):
        reroute_to.transient_signal = sig
        try:
            reroute_to.send_signal(sig)
        except ProcessLookupError:
            logger.exception("child process died unexpectedly")
    for sig in TRANSIENT_SIGLIST:
        signal.signal(sig, signal.SIG_DFL if undo else child_proc_send)


def kill_orphaned_child(wafd_imunify_daemon):
    """ if any. """
    try:
        pid = int(PIDFILE.read_text())
    except (FileNotFoundError, ValueError):
        return

    with suppress(psutil.NoSuchProcess):
        proc = psutil.Process(pid)
        if proc.name() != Path(wafd_imunify_daemon).name:
            return

        logger.error("orphaned child process: %s", proc)
        proc.terminate()
        time.sleep(2)
        proc.kill()


def daemon_being_watched() -> bool:
    wafd_imunify_daemon = '%s.bin' % sys.argv[0]
    kill_orphaned_child(wafd_imunify_daemon)
    child_proc = subprocess.Popen([wafd_imunify_daemon] + sys.argv[1:])
    child_proc.transient_signal = None
    PIDFILE.write_text('%s\n' % child_proc.pid)
    logger.info("%s has started.", wafd_imunify_daemon)

    wire_signals(reroute_to=child_proc)
    gc.collect()  # to minimize memory footprint while in idle state
    try:
        rc = child_proc.wait()
    except ProcessLookupError:
        logger.exception("child process died unexpectedly")
        return False
    finally:
        wire_signals(undo=True)

    if child_proc.transient_signal is None:
        if rc < 0:
            logger.error("%s died unexpectedly (killed by %d).",
                         wafd_imunify_daemon,
                         rc)
        else:
            logger.error("%s stopped unexpectedly (exit code %d).",
                         wafd_imunify_daemon,
                         rc)
        return False

    logger.info("%s exited with code %d (stopped by signal %d).",
                wafd_imunify_daemon,
                rc,
                child_proc.transient_signal)
    return True


def daemon_being_watched_loop() -> bool:
    failures = []
    while True:
        ok_stopped = daemon_being_watched()
        if ok_stopped:
            return True

        now = time.time()
        failures.append(now)
        if (sum(1 for timestamp in failures
                    if timestamp >= now - 60*60) >=
                MAX_FAILURES_PER_HOUR):

            return False

if __name__ == '__main__':
    try:
        logger_init()
        ok_stopped = daemon_being_watched_loop()
        if not ok_stopped:
            logger.error("wafd trouble "
                         "after %d wafd_imunify_daemon failures.",
                         MAX_FAILURES_PER_HOUR)
    except Exception as e:
        logger.exception("unexpected error: %s", e)
        sys.exit(1)