apenwarr-redo/helpers.py
Avery Pennarun 2dbd47100d state.py: reduce race condition between Lock.trylock() and unlock().
If 'redo clean' deletes the lockfile after trylock() succeeds but before
unlock(), then unlock() won't be able to open the pipe in order to release
readers, and any waiters might end up waiting forever.

We can't open the fifo for write until there's at least one reader, so let's
open a reader *just* to let us open a writer.  Then we'll leave them open
until the later unlock(), which can just close them both.
2010-11-22 04:04:45 -08:00

79 lines
1.6 KiB
Python

import sys, os, errno, fcntl
import vars
def unlink(f):
"""Delete a file at path 'f' if it currently exists.
Unlike os.unlink(), does not throw an exception if the file didn't already
exist.
"""
try:
os.unlink(f)
except OSError, e:
if e.errno == errno.ENOENT:
pass # it doesn't exist, that's what you asked for
def mkdirp(d, mode=None):
"""Recursively create directories on path 'd'.
Unlike os.makedirs(), it doesn't raise an exception if the last element of
the path already exists.
"""
try:
if mode:
os.makedirs(d, mode)
else:
os.makedirs(d)
except OSError, e:
if e.errno == errno.EEXIST:
pass
else:
raise
def log_(s):
sys.stdout.flush()
if vars.DEBUG_PIDS:
sys.stderr.write('%d %s' % (os.getpid(), s))
else:
sys.stderr.write(s)
sys.stderr.flush()
def _clog(s):
log_('\x1b[32mredo %s\x1b[1m%s\x1b[m' % (vars.DEPTH, s))
def _bwlog(s):
log_('redo %s%s' % (vars.DEPTH, s))
def _cerr(s):
log_('\x1b[31mredo: %s\x1b[1m%s\x1b[m' % (vars.DEPTH, s))
def _bwerr(s):
log_('redo: %s%s' % (vars.DEPTH, s))
if os.isatty(2):
log = _clog
err = _cerr
else:
log = _bwlog
err = _bwerr
def debug(s):
if vars.DEBUG >= 1:
log_('redo: %s%s' % (vars.DEPTH, s))
def debug2(s):
if vars.DEBUG >= 2:
log_('redo: %s%s' % (vars.DEPTH, s))
def close_on_exec(fd, yes):
fl = fcntl.fcntl(fd, fcntl.F_GETFD)
fl &= ~fcntl.FD_CLOEXEC
if yes:
fl |= fcntl.FD_CLOEXEC
fcntl.fcntl(fd, fcntl.F_SETFD, fl)