From a5ff60ccf3c957b7d225d5613100afb3c19a148c Mon Sep 17 00:00:00 2001 From: Avery Pennarun Date: Fri, 19 Nov 2010 00:57:27 -0800 Subject: [PATCH] Fix a race condition generating stampfiles. This makes 'redo -j1000' now run successfully in t/curse, except that we foolishly generate the same files more than once. But at least not more than once *in parallel*. --- redo-ifchange.py | 14 +++++++++----- redo.py | 12 +++++++----- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/redo-ifchange.py b/redo-ifchange.py index 8af42ab..3b6ca54 100755 --- a/redo-ifchange.py +++ b/redo-ifchange.py @@ -1,16 +1,20 @@ #!/usr/bin/python -import sys, os +import sys, os, errno import vars from helpers import sname, add_dep, debug, err, mkdirp, unlink def _dirty_deps(t, depth, fromdir): debug('%s?%s\n' % (depth, t)) - if not os.path.exists(sname('stamp', t, fromdir)): - debug('%s-- DIRTY (no stamp)\n' % depth) - return True + try: + stamptime = os.stat(sname('stamp', t, fromdir)).st_mtime + except OSError, e: + if e.errno == errno.ENOENT: + debug('%s-- DIRTY (no stamp)\n' % depth) + return True + else: + raise - stamptime = os.stat(sname('stamp', t, fromdir)).st_mtime try: realtime = os.stat(os.path.join(fromdir or '', t)).st_mtime except OSError: diff --git a/redo.py b/redo.py index 54dddc5..bb6b426 100755 --- a/redo.py +++ b/redo.py @@ -79,17 +79,19 @@ def find_do_file(t): def stamp(t): stampfile = sname('stamp', t) + newstampfile = sname('stamp' + str(os.getpid()), t) depfile = sname('dep', t) if not os.path.exists(vars.BASE + '/.redo'): # .redo might not exist in a 'make clean' target return - open(stampfile, 'w').close() - open(depfile, 'a').close() + open(newstampfile, 'w').close() try: mtime = os.stat(t).st_mtime except OSError: mtime = 0 - os.utime(stampfile, (mtime, mtime)) + os.utime(newstampfile, (mtime, mtime)) + os.rename(newstampfile, stampfile) + open(depfile, 'a').close() def _preexec(t): @@ -106,8 +108,8 @@ def _build(t): # an existing source file that is not marked as a generated file. # This step is mentioned by djb in his notes. It turns out to be # important to prevent infinite recursion. For example, a rule - # called default.o.do could be used to try to produce hello.c.o, - # which is stupid since hello.c is a static file. + # called default.c.do could be used to try to produce hello.c, + # which is undesirable since hello.c existed already. stamp(t) return # success unlink(sname('dep', t))