[CentralOH] SingleInstance Recipe (Windows)

William McVey wam at cisco.com
Wed Aug 4 16:06:26 CEST 2010

On Tue, 2010-08-03 at 21:04 -0400, m g wrote:
> For a simple solution on a UNIX box, I would write the process id to,
> or at least touch, /var/run/myapp.pid.  If the pid file already
> exists, I know that the application is already running. 

If you (or anyone else) decides to use a pid file (or any other constant
filename) as a locking/concurrency mechanism, please (oh please)
remember to open it like:

     fd = os.open(PIDFILE, os.O_EXCL|os.CREAT|os.O_TRUNC|os.O_WRONLY,
     os.write(fd, "%s\n" % os.getpid())
  except OSError, msg:
     sys.exit("Pidfile already exists. Exiting early: %s" % msg)

Although using os.open and os.write is a pain, it's import that the
check for the existence of the file and the creation of the file (if it
doesn't already exist) be an atomic operation. Something as simple as:

  if os.path.exists(pidfilename):
     sys.exit("Pidfile exists")
  pidfile = open(pidfilename, "w")

opens your script up to a race condition where between the execution of
the exists() and the open() call the contents of the file/directory may
have changed on you. If you're lucky, this could mean that you just have
two simultaneously running copies of your program running. If you're
unlucky and this was a malicious race exploitation, your pidfile may
have been substituted for a symlink pointing to some file that some
attacker wanted to be clobbered. I've seen essentially this same bug
exploited with vi, at, cron, mail, elm, and many other tools over the
years. It's important to not ignore the lessons of the past, even if it
is inconvenient.
  -- William

More information about the CentralOH mailing list