From c64b8a3eb1629de1a67ed7f3a039faa26e191424 Mon Sep 17 00:00:00 2001 From: Avery Pennarun Date: Sat, 11 Dec 2010 22:59:55 -0800 Subject: [PATCH] Fix a race condition caused by zap_deps(). We can't just delete all the dependencies at the beginning and re-add them: other people might be checking the same dependencies in parallel. Instead, mark them as delete_me up front, and then after the build completes, remove only the delete_me entries. --- builder.py | 8 ++++---- state.py | 15 ++++++++++----- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/builder.py b/builder.py index 0dacc1a..b8c898b 100644 --- a/builder.py +++ b/builder.py @@ -107,7 +107,7 @@ class BuildJob: sf.set_static() sf.save() return self._after2(0) - sf.zap_deps() + sf.zap_deps1() (dofile, basename, ext) = _find_do_file(sf) if not dofile: if os.path.exists(t): @@ -235,18 +235,18 @@ class BuildJob: sf.csum = None sf.update_stamp() sf.set_changed() - sf.save() else: unlink(self.tmpname1) unlink(self.tmpname2) sf = self.sf sf.set_failed() - sf.save() + sf.zap_deps2() + sf.save() f.close() if rv != 0: err('%s: exit code %d\n' % (_nice(t),rv)) else: - if vars.VERBOSE or vars.XTRACE: + if vars.VERBOSE or vars.XTRACE or vars.DEBUG: log('%s (done)\n\n' % _nice(t)) return rv diff --git a/state.py b/state.py index 5eaf1ce..63dda35 100644 --- a/state.py +++ b/state.py @@ -72,6 +72,7 @@ def db(): " (target int, " " source int, " " mode not null, " + " delete_me int, " " primary key (target,source))") _db.execute("insert into Schema (version) values (?)", [SCHEMA_VER]) # eat the '0' runid and File id @@ -253,17 +254,21 @@ class File(object): assert(mode in ('c', 'm')) yield mode,File(cols=cols) - def zap_deps(self): - debug2('zap-deps: %r\n' % self.name) - _write('delete from Deps where target=?', [self.id]) + def zap_deps1(self): + debug2('zap-deps1: %r\n' % self.name) + _write('update Deps set delete_me=? where target=?', [True, self.id]) + + def zap_deps2(self): + debug2('zap-deps2: %r\n' % self.name) + _write('delete from Deps where target=? and delete_me=1', [self.id]) def add_dep(self, mode, dep): src = File(name=dep) debug2('add-dep: %r < %s %r\n' % (self.name, mode, src.name)) assert(self.id != src.id) _write("insert or replace into Deps " - " (target, mode, source) values (?,?,?)", - [self.id, mode, src.id]) + " (target, mode, source, delete_me) values (?,?,?,?)", + [self.id, mode, src.id, False]) def read_stamp(self): try: