import os, sys, signal log_file = None log_path = None def demonize(pid_file, force=False, logfile=None): global log_file global log_path # check if pid file exists and return if not a forced start if os.path.exists(pid_file) and not force: return False ## Demonize if os.fork(): exit(0) os.umask(0) os.setsid() if os.fork(): exit(0) pid = open(pid_file,'w') pid.write(str(os.getpid())) pid.close() # The fileno is accessable after the first write sys.stdout.write('\0') sys.stderr.write('\0') sys.stdout.flush() sys.stderr.flush() ignore = open('/dev/null', 'r+') os.dup2(ignore.fileno(), sys.stdin.fileno()) if type(logfile)==file: log_file = logfile elif logfile!=None: log_file = open(logfile,'w') log_path = logfile else: log_file = ignore os.dup2(log_file.fileno(), sys.stdout.fileno()) os.dup2(log_file.fileno(), sys.stderr.fileno()) signal.signal(signal.SIGHUP, __sys_call(__sighup_handler) ) return True # decorator to make system call methods safe from EINTR def __sys_call(func): def __func(*args, **kwargs): try: rv = func(*args, **kwargs) except exception as e: if e.args and e.args[0] == EINTR: pass return rv return __func def __sighup_handler(sig,dontcare): global log_path global log_file import traceback try: if log_path != None: log_file.seek(0) log_file.close() log_file = open(log_path,'w') os.dup2(log_file.fileno(), sys.stdout.fileno()) os.dup2(log_file.fileno(), sys.stderr.fileno()) except: traceback.print_exc(file=sys.stdout) sys.exit(1)