Message9824
Currently, WeakValueDictionary.valuerefs looks like this:
return [ref(value) for value in self.itervalues()]
But, as the CPython documentation says:
Caution: Because a WeakKeyDictionary is built on top of a Python dictionary, it must not change size when iterating over it. This can be difficult to ensure for a WeakKeyDictionary because actions performed by the program during iteration may cause items in the dictionary to vanish “by magic” (as a side effect of garbage collection).
This is enforced by the Jython dictionary implementation, and together with of having Java's truly non-deterministic GC means that using itervalues is extremely dangerous. Practically speaking, this makes `valuerefs` impossible to use.
This came up in porting the widely used `transaction` package to work on Jython[1]. When the system is put under any strain, a RuntimeError results from this method. Here's an example from running the ZODB test suite; changing `itervalues` to `values` solves the problem:
File "<doctest ZODB.tests.testblob.loadblob_tmpstore[12]>", line 1, in <module>
database.close()
File "//ZODB/src/ZODB/DB.py", line 629, in close
@self._connectionMap
File "//ZODB/src/ZODB/DB.py", line 505, in _connectionMap
self.pool.map(f)
File "//ZODB/src/ZODB/DB.py", line 205, in map
self.all.map(f)
File "//transaction-1.4.4.dev0-py2.7.egg/transaction/weakset.py", line 63, in map
f(elt)
File "//ZODB/src/ZODB/DB.py", line 631, in _
c.transaction_manager.abort()
File "//transaction-1.4.4.dev0-py2.7.egg/transaction/_manager.py", line 116, in abort
return self.get().abort()
File "//transaction-1.4.4.dev0-py2.7.egg/transaction/_transaction.py", line 443, in abort
self._synchronizers.map(lambda s: s.beforeCompletion(self))
File "//transaction-1.4.4.dev0-py2.7.egg/transaction/weakset.py", line 60, in map
for wr in self.as_weakref_list():
File "//transaction-1.4.4.dev0-py2.7.egg/transaction/weakset.py", line 87, in as_weakref_list
refs = self.data.valuerefs()
File "//jython2.7rc2/Lib/weakref.py", line 69, in valuerefs
return [ref(value) for value in self.itervalues()]
RuntimeError: dictionary changed size during iteration
The same reasoning for `WeakKeyDictionary.keyrefs`
[1] https://github.com/zopefoundation/transaction/pull/8 |
|
Date |
User |
Action |
Args |
2015-04-14 02:10:05 | jmadden | set | recipients:
+ jmadden |
2015-04-14 02:10:04 | jmadden | set | messageid: <1428977404.9.0.392233485787.issue2326@psf.upfronthosting.co.za> |
2015-04-14 02:10:04 | jmadden | link | issue2326 messages |
2015-04-14 02:10:03 | jmadden | create | |
|