def fork_in_bg(function, *args): # fork and call a function with args # return a dict with {'r': fd, 'pid': pid} where fd is the stdout from a pipe. # example: # def add(i, j): return i+j # d = fork_in_bg(add, i, j) r, w = os.pipe() unregister_sighandler() pid = os.fork() if pid == 0: logSupport.disable_rotate = True os.close(r) try: out = function(*args) os.write(w, cPickle.dumps(out)) except: logSupport.log.warning("Forked process '%s' failed" % str(function)) logSupport.log.exception("Forked process '%s' failed" % str(function)) finally: os.close(w) # Exit, immediately. Don't want any cleanup, since I was created # just for performing the work os._exit(0) else: register_sighandler() os.close(w) return {'r': r, 'pid': pid}
def start_background_cleanup(self): if self.cleanup_pids: logSupport.log.warning("Earlier cleanup PIDs %s still exist; skipping this cycle" % self.cleanup_pids) else: num_forks = 4 # arbitrary - could be configurable cleanup_lists = [self.cleanup_objects[x::num_forks] for x in xrange(num_forks)] for i in xrange(num_forks): unregister_sighandler() cl_pid = os.fork() if cl_pid != 0: register_sighandler() self.cleanup_pids.append(cl_pid) else: for cleaner in cleanup_lists[i]: cleaner.cleanup() os._exit(0) logSupport.log.debug("Forked cleanup PIDS %s" % self.cleanup_pids) del cleanup_lists