Move env.{add,get}_lock() into cycles.py, and rename.
They really aren't locks at all, they're a cycle detector. Also rename REDO_LOCKS to a more meaningful REDO_CYCLES. And we'll move the CyclicDependencyError exception in here as well, instead of state.py where it doesn't really belong.
This commit is contained in:
parent
ded14507b0
commit
f1305b49eb
5 changed files with 32 additions and 25 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
import sys, os, errno, stat, signal, time
|
import sys, os, errno, stat, signal, time
|
||||||
import env, jobserver, state, paths
|
import cycles, env, jobserver, state, paths
|
||||||
from helpers import unlink, close_on_exec
|
from helpers import unlink, close_on_exec
|
||||||
import logs
|
import logs
|
||||||
from logs import debug2, err, warn, meta, check_tty
|
from logs import debug2, err, warn, meta, check_tty
|
||||||
|
|
@ -129,7 +129,7 @@ class BuildJob(object):
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
is_target, dirty = self.shouldbuildfunc(self.t)
|
is_target, dirty = self.shouldbuildfunc(self.t)
|
||||||
except state.CyclicDependencyError:
|
except cycles.CyclicDependencyError:
|
||||||
err('cyclic dependency while checking %s\n' % _nice(self.t))
|
err('cyclic dependency while checking %s\n' % _nice(self.t))
|
||||||
raise ImmediateReturn(208)
|
raise ImmediateReturn(208)
|
||||||
if not dirty:
|
if not dirty:
|
||||||
|
|
@ -264,7 +264,7 @@ class BuildJob(object):
|
||||||
os.environ['REDO_PWD'] = state.relpath(newp, env.STARTDIR)
|
os.environ['REDO_PWD'] = state.relpath(newp, env.STARTDIR)
|
||||||
os.environ['REDO_TARGET'] = self.basename + self.ext
|
os.environ['REDO_TARGET'] = self.basename + self.ext
|
||||||
os.environ['REDO_DEPTH'] = env.DEPTH + ' '
|
os.environ['REDO_DEPTH'] = env.DEPTH + ' '
|
||||||
env.add_lock(str(self.lock.fid))
|
cycles.add(self.lock.fid)
|
||||||
if dn:
|
if dn:
|
||||||
os.chdir(dn)
|
os.chdir(dn)
|
||||||
os.dup2(self.f.fileno(), 1)
|
os.dup2(self.f.fileno(), 1)
|
||||||
|
|
@ -499,7 +499,7 @@ def main(targets, shouldbuildfunc):
|
||||||
meta('waiting', state.target_relpath(t))
|
meta('waiting', state.target_relpath(t))
|
||||||
try:
|
try:
|
||||||
lock.check()
|
lock.check()
|
||||||
except state.CyclicDependencyError:
|
except cycles.CyclicDependencyError:
|
||||||
err('cyclic dependency while building %s\n' % _nice(t))
|
err('cyclic dependency while building %s\n' % _nice(t))
|
||||||
retcode[0] = 208
|
retcode[0] = 208
|
||||||
return retcode[0]
|
return retcode[0]
|
||||||
|
|
|
||||||
24
redo/cycles.py
Normal file
24
redo/cycles.py
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
"""Code for detecting and aborting on cyclic dependency loops."""
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
class CyclicDependencyError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def _get():
|
||||||
|
"""Get the list of held cycle items."""
|
||||||
|
return os.environ.get('REDO_CYCLES', '').split(':')
|
||||||
|
|
||||||
|
|
||||||
|
def add(fid):
|
||||||
|
"""Add a lock to the list of held cycle items."""
|
||||||
|
items = set(_get())
|
||||||
|
items.add(str(fid))
|
||||||
|
os.environ['REDO_CYCLES'] = ':'.join(list(items))
|
||||||
|
|
||||||
|
|
||||||
|
def check(fid):
|
||||||
|
if str(fid) in _get():
|
||||||
|
# Lock already held by parent: cyclic dependency
|
||||||
|
raise CyclicDependencyError()
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import os
|
import os
|
||||||
import env, state
|
import cycles, env, state
|
||||||
from logs import debug
|
from logs import debug
|
||||||
|
|
||||||
CLEAN = 0
|
CLEAN = 0
|
||||||
|
|
@ -11,7 +11,7 @@ def isdirty(f, depth, max_changed,
|
||||||
set_checked=state.File.set_checked_save,
|
set_checked=state.File.set_checked_save,
|
||||||
log_override=state.warn_override):
|
log_override=state.warn_override):
|
||||||
if f.id in already_checked:
|
if f.id in already_checked:
|
||||||
raise state.CyclicDependencyError()
|
raise cycles.CyclicDependencyError()
|
||||||
# make a copy of the list, so upon returning, our parent's copy
|
# make a copy of the list, so upon returning, our parent's copy
|
||||||
# is unaffected
|
# is unaffected
|
||||||
already_checked = list(already_checked) + [f.id]
|
already_checked = list(already_checked) + [f.id]
|
||||||
|
|
|
||||||
11
redo/env.py
11
redo/env.py
|
|
@ -33,14 +33,3 @@ os.environ['REDO_UNLOCKED'] = '' # not inheritable by subprocesses
|
||||||
|
|
||||||
NO_OOB = os.environ.get('REDO_NO_OOB', '') and 1 or 0
|
NO_OOB = os.environ.get('REDO_NO_OOB', '') and 1 or 0
|
||||||
os.environ['REDO_NO_OOB'] = '' # not inheritable by subprocesses
|
os.environ['REDO_NO_OOB'] = '' # not inheritable by subprocesses
|
||||||
|
|
||||||
|
|
||||||
def get_locks():
|
|
||||||
"""Get the list of held locks."""
|
|
||||||
return os.environ.get('REDO_LOCKS', '').split(':')
|
|
||||||
|
|
||||||
def add_lock(name):
|
|
||||||
"""Add a lock to the list of held locks."""
|
|
||||||
locks = set(get_locks())
|
|
||||||
locks.add(name)
|
|
||||||
os.environ['REDO_LOCKS'] = ':'.join(list(locks))
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import sys, os, errno, stat, fcntl, sqlite3
|
import sys, os, errno, stat, fcntl, sqlite3
|
||||||
import env
|
import cycles, env
|
||||||
from helpers import unlink, close_on_exec, join
|
from helpers import unlink, close_on_exec, join
|
||||||
from logs import warn, debug2, debug3
|
from logs import warn, debug2, debug3
|
||||||
|
|
||||||
|
|
@ -24,10 +24,6 @@ STAMP_MISSING = '0' # the stamp of a nonexistent file
|
||||||
LOG_LOCK_MAGIC = 0x10000000 # fid offset for "log locks"
|
LOG_LOCK_MAGIC = 0x10000000 # fid offset for "log locks"
|
||||||
|
|
||||||
|
|
||||||
class CyclicDependencyError(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def _connect(dbfile):
|
def _connect(dbfile):
|
||||||
_db = sqlite3.connect(dbfile, timeout=TIMEOUT)
|
_db = sqlite3.connect(dbfile, timeout=TIMEOUT)
|
||||||
_db.execute("pragma synchronous = off")
|
_db.execute("pragma synchronous = off")
|
||||||
|
|
@ -466,9 +462,7 @@ class Lock(object):
|
||||||
|
|
||||||
def check(self):
|
def check(self):
|
||||||
assert not self.owned
|
assert not self.owned
|
||||||
if str(self.fid) in env.get_locks():
|
cycles.check(self.fid)
|
||||||
# Lock already held by parent: cyclic dependence
|
|
||||||
raise CyclicDependencyError()
|
|
||||||
|
|
||||||
def trylock(self):
|
def trylock(self):
|
||||||
self.check()
|
self.check()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue