Replace lockfile stuff with fifos instead.

Now people waiting for a lock can wait for the fifo to be ready, which means
it's instant instead of polled.  Very pretty.  Probably doesn't work on
Windows though.
This commit is contained in:
Avery Pennarun 2010-11-18 22:43:39 -08:00
commit 2b71e662cb

42
redo.py
View file

@ -156,21 +156,31 @@ def build(t):
mkdirp('%s/.redo' % vars.BASE) mkdirp('%s/.redo' % vars.BASE)
lockname = sname('lock', t) lockname = sname('lock', t)
try: try:
fd = os.open(lockname, os.O_CREAT|os.O_EXCL) os.mkfifo(lockname, 0600)
except OSError, e: except OSError, e:
if e.errno == errno.EEXIST: if e.errno == errno.EEXIST:
log('%s (locked...)\n' % relpath(t, vars.STARTDIR)) log('%s (locked...)\n' % relpath(t, vars.STARTDIR))
os._exit(199) os._exit(199)
else: else:
raise raise
os.close(fd)
try: try:
try: try:
return _build(t) return _build(t)
except BuildError, e: except BuildError, e:
err('%s\n' % e) err('%s\n' % e)
finally: finally:
fd = None
try:
fd = os.open(lockname, os.O_WRONLY|os.O_NONBLOCK)
except OSError, e:
if e.errno == errno.ENXIO: # no readers open; that's ok
pass
elif e.errno == errno.ENOENT: # 'make clean' might do this
pass
else:
raise
unlink(lockname) unlink(lockname)
if fd != None: os.close(fd)
os._exit(1) os._exit(1)
@ -194,18 +204,22 @@ def main():
elif pd.rv: elif pd.rv:
err('%s: exit code was %r\n' % (t, pd.rv)) err('%s: exit code was %r\n' % (t, pd.rv))
retcode = 1 retcode = 1
while locked: for t in locked.keys():
for t in locked.keys(): lockname = sname('lock', t)
lockname = sname('lock', t) stampname = sname('stamp', t)
stampname = sname('stamp', t) try:
if not os.path.exists(lockname): # open() will finish only when an existing writer does close()
relp = relpath(t, vars.STARTDIR) os.close(os.open(lockname, os.O_RDONLY))
log('%s (...unlocked!)\n' % relp) except OSError, e:
if not os.path.exists(stampname): if e.errno == errno.ENOENT:
err('%s: failed in another thread\n' % relp) pass # already got unlocked
retcode = 2 else:
del locked[t] raise
time.sleep(0.2) relp = relpath(t, vars.STARTDIR)
log('%s (...unlocked!)\n' % relp)
if not os.path.exists(stampname):
err('%s: failed in another thread\n' % relp)
retcode = 2
return retcode return retcode