Commit eb53b7aa authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent a02f19de
#!/usr/bin/env python #!/usr/bin/env python
# XXX doc """Program zopenrace.py demonstrates race-condition bug in ZODB
# Connection.open() that leads to stale live cache and wrong data provided by
#newTransaction database to users.
# ._storage.sync()
# invalidated = ._storage.poll_invalidations():
# newTransaction
# ._storage._start = ._storage._storage.lastTrasaction() + 1: ._storage.sync()
# s = ._storage._storage invalidated = ._storage.poll_invalidations():
# s._lock.acquire()
# head = s._ltid ._storage._start = ._storage._storage.lastTrasaction() + 1:
# s._lock.release() s = ._storage._storage
# return head s._lock.acquire()
# XXX T2 commits here: objX head = s._ltid
# s._lock.release()
# ._storage._lock.acquire() return head
# r = _storage._invalidations ; T1 receives invalidations for some transactions after head XXX T2 commits here: objX
# ._storage._lock.release()
# return r ._storage._lock.acquire()
# r = _storage._invalidations ; T1 receives invalidations for some transactions after head
# # T1 processes invalidates for [... head] _and_ some next transactions. ._storage._lock.release()
# # T1 thus will _not_ process invalidations for those next transactions when return r
# # opening zconn _next_ time. The next opened zconn will thus see _stale_ data.
# ._cache.invalidate(invalidated) # T1 processes invalidates for [... head] _and_ some next transactions.
# T1 thus will _not_ process invalidations for those next transactions when
# opening zconn _next_ time. The next opened zconn will thus see _stale_ data.
._cache.invalidate(invalidated)
"""
from ZODB import DB from ZODB import DB
from ZODB.MappingStorage import MappingStorage from ZODB.MappingStorage import MappingStorage
...@@ -39,8 +43,7 @@ def go(f, *argv, **kw): ...@@ -39,8 +43,7 @@ def go(f, *argv, **kw):
return t return t
# PInt is persistent integer.
# PInt is persistent integer:
class PInt(Persistent): class PInt(Persistent):
def __init__(self, i): def __init__(self, i):
self.i = i self.i = i
...@@ -51,6 +54,7 @@ def main(): ...@@ -51,6 +54,7 @@ def main():
db = DB(zstor) db = DB(zstor)
# init initializes the database with two integer objects - obj1/obj2 that are set to 0.
def init(): def init():
transaction.begin() transaction.begin()
zconn = db.open() zconn = db.open()
...@@ -119,9 +123,11 @@ def main(): ...@@ -119,9 +123,11 @@ def main():
okv[1] = True okv[1] = True
N = 1000 # run T1 and T2 concurrently. As of 20191210, due to race condition in
# Connection.open, it triggers the bug where T1 sees stale obj2 with obj1.i != obj2.i
init() init()
N = 1000
t1 = go(T1, N) t1 = go(T1, N)
t2 = go(T2, N) t2 = go(T2, N)
t1.join() t1.join()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment