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.
This commit is contained in:
Avery Pennarun 2010-12-11 22:59:55 -08:00
commit c64b8a3eb1
2 changed files with 14 additions and 9 deletions

View file

@ -107,7 +107,7 @@ class BuildJob:
sf.set_static() sf.set_static()
sf.save() sf.save()
return self._after2(0) return self._after2(0)
sf.zap_deps() sf.zap_deps1()
(dofile, basename, ext) = _find_do_file(sf) (dofile, basename, ext) = _find_do_file(sf)
if not dofile: if not dofile:
if os.path.exists(t): if os.path.exists(t):
@ -235,18 +235,18 @@ class BuildJob:
sf.csum = None sf.csum = None
sf.update_stamp() sf.update_stamp()
sf.set_changed() sf.set_changed()
sf.save()
else: else:
unlink(self.tmpname1) unlink(self.tmpname1)
unlink(self.tmpname2) unlink(self.tmpname2)
sf = self.sf sf = self.sf
sf.set_failed() sf.set_failed()
sf.save() sf.zap_deps2()
sf.save()
f.close() f.close()
if rv != 0: if rv != 0:
err('%s: exit code %d\n' % (_nice(t),rv)) err('%s: exit code %d\n' % (_nice(t),rv))
else: else:
if vars.VERBOSE or vars.XTRACE: if vars.VERBOSE or vars.XTRACE or vars.DEBUG:
log('%s (done)\n\n' % _nice(t)) log('%s (done)\n\n' % _nice(t))
return rv return rv

View file

@ -72,6 +72,7 @@ def db():
" (target int, " " (target int, "
" source int, " " source int, "
" mode not null, " " mode not null, "
" delete_me int, "
" primary key (target,source))") " primary key (target,source))")
_db.execute("insert into Schema (version) values (?)", [SCHEMA_VER]) _db.execute("insert into Schema (version) values (?)", [SCHEMA_VER])
# eat the '0' runid and File id # eat the '0' runid and File id
@ -253,17 +254,21 @@ class File(object):
assert(mode in ('c', 'm')) assert(mode in ('c', 'm'))
yield mode,File(cols=cols) yield mode,File(cols=cols)
def zap_deps(self): def zap_deps1(self):
debug2('zap-deps: %r\n' % self.name) debug2('zap-deps1: %r\n' % self.name)
_write('delete from Deps where target=?', [self.id]) _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): def add_dep(self, mode, dep):
src = File(name=dep) src = File(name=dep)
debug2('add-dep: %r < %s %r\n' % (self.name, mode, src.name)) debug2('add-dep: %r < %s %r\n' % (self.name, mode, src.name))
assert(self.id != src.id) assert(self.id != src.id)
_write("insert or replace into Deps " _write("insert or replace into Deps "
" (target, mode, source) values (?,?,?)", " (target, mode, source, delete_me) values (?,?,?,?)",
[self.id, mode, src.id]) [self.id, mode, src.id, False])
def read_stamp(self): def read_stamp(self):
try: try: