fix race condition as reported by Ralf Schmitt
This commit is contained in:
@@ -5,6 +5,9 @@
|
|||||||
|
|
||||||
- fix issue34 - distributed testing with -p plugin now works correctly
|
- fix issue34 - distributed testing with -p plugin now works correctly
|
||||||
|
|
||||||
|
- fix race condition in looponfail mode where a concurrent file removal
|
||||||
|
could cause a crash
|
||||||
|
|
||||||
1.5
|
1.5
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ class TestStatRecorder:
|
|||||||
changed = sd.check()
|
changed = sd.check()
|
||||||
assert changed
|
assert changed
|
||||||
|
|
||||||
tmp.ensure("new.py")
|
p = tmp.ensure("new.py")
|
||||||
changed = sd.check()
|
changed = sd.check()
|
||||||
assert changed
|
assert changed
|
||||||
|
|
||||||
tmp.join("new.py").remove()
|
p.remove()
|
||||||
changed = sd.check()
|
changed = sd.check()
|
||||||
assert changed
|
assert changed
|
||||||
|
|
||||||
@@ -36,6 +36,24 @@ class TestStatRecorder:
|
|||||||
changed = sd.check()
|
changed = sd.check()
|
||||||
assert changed
|
assert changed
|
||||||
|
|
||||||
|
def test_filechange_deletion_race(self, tmpdir, monkeypatch):
|
||||||
|
tmp = tmpdir
|
||||||
|
sd = StatRecorder([tmp])
|
||||||
|
changed = sd.check()
|
||||||
|
assert not changed
|
||||||
|
|
||||||
|
p = tmp.ensure("new.py")
|
||||||
|
changed = sd.check()
|
||||||
|
assert changed
|
||||||
|
|
||||||
|
p.remove()
|
||||||
|
# make check()'s visit() call return our just removed
|
||||||
|
# path as if we were in a race condition
|
||||||
|
monkeypatch.setattr(tmp, 'visit', lambda *args: [p])
|
||||||
|
|
||||||
|
changed = sd.check()
|
||||||
|
assert changed
|
||||||
|
|
||||||
def test_pycremoval(self, tmpdir):
|
def test_pycremoval(self, tmpdir):
|
||||||
tmp = tmpdir
|
tmp = tmpdir
|
||||||
hello = tmp.ensure("hello.py")
|
hello = tmp.ensure("hello.py")
|
||||||
|
|||||||
@@ -201,14 +201,11 @@ class StatRecorder:
|
|||||||
newstat = {}
|
newstat = {}
|
||||||
for rootdir in self.rootdirlist:
|
for rootdir in self.rootdirlist:
|
||||||
for path in rootdir.visit(self.fil, self.rec):
|
for path in rootdir.visit(self.fil, self.rec):
|
||||||
oldstat = statcache.get(path, None)
|
oldstat = statcache.pop(path, None)
|
||||||
if oldstat is not None:
|
|
||||||
del statcache[path]
|
|
||||||
try:
|
try:
|
||||||
newstat[path] = curstat = path.stat()
|
newstat[path] = curstat = path.stat()
|
||||||
except py.error.ENOENT:
|
except py.error.ENOENT:
|
||||||
if oldstat:
|
if oldstat:
|
||||||
del statcache[path]
|
|
||||||
changed = True
|
changed = True
|
||||||
else:
|
else:
|
||||||
if oldstat:
|
if oldstat:
|
||||||
|
|||||||
Reference in New Issue
Block a user