Author: Armin Rigo <[email protected]>
Branch:
Changeset: r2977:75275c539e51
Date: 2017-06-15 10:19 +0200
http://bitbucket.org/cffi/cffi/changeset/75275c539e51/
Log: Issue #319
Fix a race condition: we can't stick an attribute to ffi._backend,
because another thread might be in the middle of ``for name in
ffi._backend.__dict__``.
To minimize damage if I reintroduce an attribute-adding function in
the future, also tweak the ``for``.
diff --git a/cffi/api.py b/cffi/api.py
--- a/cffi/api.py
+++ b/cffi/api.py
@@ -75,9 +75,10 @@
self._init_once_cache = {}
self._cdef_version = None
self._embedding = None
+ self._typecache = model.get_typecache(backend)
if hasattr(backend, 'set_ffi'):
backend.set_ffi(self)
- for name in backend.__dict__:
+ for name in list(backend.__dict__):
if name.startswith('RTLD_'):
setattr(self, name, getattr(backend, name))
#
diff --git a/cffi/model.py b/cffi/model.py
--- a/cffi/model.py
+++ b/cffi/model.py
@@ -568,22 +568,26 @@
global_lock = allocate_lock()
+_typecache_cffi_backend = weakref.WeakValueDictionary()
+
+def get_typecache(backend):
+ # returns _typecache_cffi_backend if backend is the _cffi_backend
+ # module, or type(backend).__typecache if backend is an instance of
+ # CTypesBackend (or some FakeBackend class during tests)
+ if isinstance(backend, types.ModuleType):
+ return _typecache_cffi_backend
+ with global_lock:
+ if not hasattr(type(backend), '__typecache'):
+ type(backend).__typecache = weakref.WeakValueDictionary()
+ return type(backend).__typecache
def global_cache(srctype, ffi, funcname, *args, **kwds):
key = kwds.pop('key', (funcname, args))
assert not kwds
try:
- return ffi._backend.__typecache[key]
+ return ffi._typecache[key]
except KeyError:
pass
- except AttributeError:
- # initialize the __typecache attribute, either at the module level
- # if ffi._backend is a module, or at the class level if ffi._backend
- # is some instance.
- if isinstance(ffi._backend, types.ModuleType):
- ffi._backend.__typecache = weakref.WeakValueDictionary()
- else:
- type(ffi._backend).__typecache = weakref.WeakValueDictionary()
try:
res = getattr(ffi._backend, funcname)(*args)
except NotImplementedError as e:
@@ -591,7 +595,7 @@
# note that setdefault() on WeakValueDictionary is not atomic
# and contains a rare bug (http://bugs.python.org/issue19542);
# we have to use a lock and do it ourselves
- cache = ffi._backend.__typecache
+ cache = ffi._typecache
with global_lock:
res1 = cache.get(key)
if res1 is None:
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit