def start(self, name, program, *args, **kargs): tracedir = kargs.get("trace_dir") appdir = kargs.get("app_dir") pidfile = joinpths(tracedir, name + ".pid") stderr = joinpths(tracedir, name + ".stderr") stdout = joinpths(tracedir, name + ".stdout") tracefn = Trace.trace_fn(tracedir, name) tracefn = Trace.touch_trace(tracedir, name) runtrace = Trace.Trace(tracefn) runtrace.trace(RUN, RUN_TYPE) runtrace.trace(PID_FN, pidfile) runtrace.trace(STDERR_FN, stderr) runtrace.trace(STDOUT_FN, stdout) #fork to get daemon out pid = os.fork() if(pid == 0): os.setsid() pid = os.fork() #fork to get daemon out - this time under init control #and now fully detached (no shell possible) if(pid == 0): #move to where application should be os.chdir(appdir) #close other fds limits = resource.getrlimit(resource.RLIMIT_NOFILE) mkfd = limits[1] if(mkfd == resource.RLIM_INFINITY): mkfd = MAXFD for fd in range(0, mkfd): try: os.close(fd) except OSError: #not open, thats ok pass #now adjust stderr and stdout stdoh = open(stdout, "w") stdeh = open(stderr, "w") os.dup2(stdoh.fileno(), sys.stdout.fileno()) os.dup2(stdeh.fileno(), sys.stderr.fileno()) #now exec... #the arguments to the child process should #start with the name of the command being run actualargs = [program] + list(args) os.execlp(program, *actualargs) else: #write out the child pid contents = str(pid) + "\n" write_file(pidfile, contents) #not exit or sys.exit, this is recommended #since it will do the right cleanups that we want #not calling any atexit functions, which would #be bad right now os._exit(0) else: return tracefn
def stop(self, name, *args, **kargs): rootdir = kargs.get("trace_dir") pidfile = joinpths(rootdir, name + ".pid") stderr = joinpths(rootdir, name + ".stderr") stdout = joinpths(rootdir, name + ".stdout") tfname = Trace.trace_fn(rootdir, name) if(isfile(pidfile) and isfile(tfname)): pid = int(load_file(pidfile).strip()) killed = False lastmsg = "" attempts = 1 for attempt in range(0, MAX_KILL_TRY): try: os.kill(pid, signal.SIGKILL) attempts += 1 except OSError as (ec, msg): if(ec == errno.ESRCH): killed = True break else: lastmsg = msg time.sleep(SLEEP_TIME) #trash the files if(killed): LOG.info("Killed pid %s in %s attempts" % (str(pid), str(attempts))) LOG.info("Removing pid file %s" % (pidfile)) unlink(pidfile) LOG.info("Removing stderr file %s" % (stderr)) unlink(stderr) LOG.info("Removing stdout file %s" % (stdout)) unlink(stdout) LOG.info("Removing %s trace file %s" % (name, tfname)) unlink(tfname) else: msg = "Could not stop program named %s after %s attempts - [%s]" % (name, MAX_KILL_TRY, lastmsg) raise StopException(msg)