def claim_pidfile(pidfile_name): """Ensure that we are the only process running that is unique to using the given pidfile name. This is (modulo bugs) guaranteed to work for all code using this function. We clean up after ourselves on exit, so do not manage the file otherwise; you should only manage the name of the file. NOTE: This will not work if the filesystem is NFS! http://sandbox.chad.org/python_pid_file_usage Copyright Chad Miller, 2008, LGPL. version 0.2 TODO: make a stale file timeout for the empty/corrupt-file case. """ import os, errno, atexit def find_pid(): f = open(pidfile_name, "r") p = f.read() f.close() return int(p.strip()) succeeded = False for attempt_number in range(10): try: fd = os.open(pidfile_name, os.O_WRONLY|os.O_CREAT|os.O_EXCL) except OSError: # Assumption: The file does not exist because of us. We are # not responsible for removing it. try: p = find_pid() except (IOError, OSError,): # File not exists or some unknown problem. Try again. continue except ValueError: # Empty/corrupt-file case. Another process may be writing # here right now. Not safe to remove. This is trouble. continue try: os.kill(p, 0) # Dummy signal. Tests process existence. return None # A process really exists. Stop trying. except os.error, detail: if detail.errno in (errno.ESRCH, errno.EPERM): os.unlink(pidfile_name) continue else: # We created it. We must destroy it. atexit.register(lambda: os.unlink(pidfile_name)) try: os.write(fd, "%d" % os.getpid()) os.close(fd) succeeded = True break except OSError: os.unlink(pidfile_name) # We created it. We must destroy it. continue return succeeded