diff --git a/warden3/contrib/warden_filer/warden_filer.py b/warden3/contrib/warden_filer/warden_filer.py index e8d4c96c474e285d51b7eba63c0cd83d4a219f77..00c55b614847e27862ab1b8e4db71b00d4b91a2a 100644 --- a/warden3/contrib/warden_filer/warden_filer.py +++ b/warden3/contrib/warden_filer/warden_filer.py @@ -14,12 +14,11 @@ import socket import time import logging import signal -import lockfile +import resource +import atexit import argparse from os import path, mkdir from random import choice, randint; -from daemon import DaemonContext -from daemon.pidlockfile import TimeoutPIDLockFile VERSION = "3.0-beta1" @@ -323,6 +322,61 @@ def get_logger_files(logger): +def daemonize( + work_dir = None, chroot_dir = None, + umask = None, uid = None, gid = None, + pidfile = None, files_preserve = [], signals = {}): + # Dirs, limits, users + if chroot_dir is not None: + os.chdir(chroot_dir) + os.chroot(chroot_dir) + if umask is not None: + os.umask(umask) + if work_dir is not None: + os.chdir(work_dir) + if gid is not None: + os.setgid(gid) + if uid is not None: + os.setuid(uid) + # Doublefork, split session + if os.fork()>0: + os._exit(0) + os.setsid() + if os.fork()>0: + os._exit(0) + # Setup signal handlers + for (signum, handler) in signals.items(): + signal.signal(signum, handler) + # Close descriptors + descr_preserve = set(f.fileno() for f in files_preserve) + maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1] + if maxfd==resource.RLIM_INFINITY: + maxfd = 65535 + for fd in range(maxfd, 3, -1): # 3 means omit stdin, stdout, stderr + if fd not in descr_preserve: + try: + os.close(fd) + except Exception: + pass + # Redirect stdin, stdout, stderr to /dev/null + devnull = os.open(os.devnull, os.O_RDWR) + for fd in range(3): + os.dup2(devnull, fd) + # PID file + if pidfile is not None: + pidd = os.open(pidfile, os.O_RDWR|os.O_CREAT|os.O_EXCL|os.O_TRUNC) + os.write(pidd, str(os.getpid())+"\n") + os.close(pidd) + # Define and setup atexit closure + @atexit.register + def unlink_pid(): + try: + os.unlink(pidfile) + except Exception: + pass + + + running_flag = True # Daemon cleanly exits when set to False def terminate_me(signum, frame): @@ -391,42 +445,29 @@ if __name__ == "__main__": wconfig, fconfig = get_configs() - safe_dir = SafeDir(fconfig.get("dir", args.func)) - wclient = Client(**wconfig) - if not args.daemon: - daemon = DummyContext() - else: - work_dir = fconfig.get("work_dir", ".") - chroot_dir = fconfig.get("chroot_dir") - umask = fconfig.get("umask", 0) - pid_file = args.pid_file - uid = fconfig.get("uid") - gid = fconfig.get("gid") - - daemon = DaemonContext( - working_directory = work_dir, - chroot_directory = chroot_dir, - umask = umask, - pidfile = TimeoutPIDLockFile(pid_file, acquire_timeout=0) if pid_file else None, - uid = uid, - gid = gid, - files_preserve = get_logger_files(wclient.logger), - signal_map = { - signal.SIGTERM: terminate_me, - signal.SIGINT: terminate_me, - signal.SIGHUP: None - } - ) - try: - with daemon: - wclient.logger.info("Starting %s" % args.func) - function(fconfig, wclient, safe_dir, args.oneshot) - wclient.logger.info("Exiting %s" % args.func) - except lockfile.Error as e: - wclient.logger.critical("Error acquiring lockfile %s (%s)" - % (daemon.pidfile.lock_file, type(e).__name__)) - except Exception: - wclient.logger.critical("%s daemon error" % args.func, exc_info=sys.exc_info()) + if args.daemon: + daemonize( + work_dir = fconfig.get("work_dir", "."), + chroot_dir = fconfig.get("chroot_dir"), + umask = fconfig.get("umask"), + uid = fconfig.get("uid"), + gid = fconfig.get("gid"), + pidfile = args.pid_file, + files_preserve = get_logger_files(wclient.logger), + signals = { + signal.SIGTERM: terminate_me, + signal.SIGINT: terminate_me, + signal.SIGHUP: signal.SIG_IGN, + signal.SIGTTIN: signal.SIG_IGN, + signal.SIGTTOU: signal.SIG_IGN}) + + safe_dir = SafeDir(fconfig.get("dir", args.func)) + wclient.logger.info("Starting %s" % args.func) + function(fconfig, wclient, safe_dir, args.oneshot) + wclient.logger.info("Exiting %s" % args.func) + + except Exception as e: + Error(message="%s daemon error" % args.func, exc=sys.exc_info()).log(wclient.logger)