Author: Armin Rigo <ar...@tunes.org>
Branch: py3.6
Changeset: r98301:ae244c1519cf
Date: 2019-12-16 19:09 +0100
http://bitbucket.org/pypy/pypy/changeset/ae244c1519cf/

Log:    hg merge default

diff --git a/.hgtags b/.hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -59,3 +59,5 @@
 5da45ced70e515f94686be0df47c59abd1348ebc release-pypy3.6-v7.2.0
 e6471221abc16f4584a07fbfeece7ebcaeb7fc38 release-pypy2.7-v7.3.0rc1
 533398cfd64e5146a07c4824e90a1b629c8b6523 release-pypy3.6-v7.3.0rc1
+285307a0f5a77ffa46781b5c54c52eb1c385081d release-pypy2.7-v7.3.0rc2
+008914050baeedb6d3ca30fe26ef43b78bb63841 release-pypy3.6-v7.3.0rc2
diff --git a/pypy/module/_cffi_backend/realize_c_type.py 
b/pypy/module/_cffi_backend/realize_c_type.py
--- a/pypy/module/_cffi_backend/realize_c_type.py
+++ b/pypy/module/_cffi_backend/realize_c_type.py
@@ -83,6 +83,8 @@
         self.space = space
         self.all_primitives = [None] * cffi_opcode._NUM_PRIM
         self.file_struct = None
+        self.lock = None
+        self.lock_owner = 0
         self.rec_level = 0
 
     def get_file_struct(self):
@@ -90,6 +92,33 @@
             self.file_struct = ctypestruct.W_CTypeStruct(self.space, "FILE")
         return self.file_struct
 
+    def __enter__(self):
+        # This is a simple recursive lock implementation
+        if self.space.config.objspace.usemodules.thread:
+            from rpython.rlib import rthread
+            #
+            tid = rthread.get_ident()
+            if tid != self.lock_owner:
+                if self.lock is None:
+                    self.lock = self.space.allocate_lock()
+                self.lock.acquire(True)
+                assert self.lock_owner == 0
+                assert self.rec_level == 0
+                self.lock_owner = tid
+        self.rec_level += 1
+
+    def __exit__(self, *args):
+        assert self.rec_level > 0
+        self.rec_level -= 1
+        if self.space.config.objspace.usemodules.thread:
+            from rpython.rlib import rthread
+            #
+            tid = rthread.get_ident()
+            assert tid == self.lock_owner
+            if self.rec_level == 0:
+                self.lock_owner = 0
+                self.lock.release()
+
 
 def get_primitive_type(ffi, num):
     space = ffi.space
@@ -408,17 +437,20 @@
         return ffi.cached_types[index]
 
     realize_cache = ffi.space.fromcache(RealizeCache)
-    if realize_cache.rec_level >= 1000:
-        raise oefmt(ffi.space.w_RuntimeError,
-            "type-building recursion too deep or infinite.  "
-            "This is known to occur e.g. in ``struct s { void(*callable)"
-            "(struct s); }''.  Please report if you get this error and "
-            "really need support for your case.")
-    realize_cache.rec_level += 1
-    try:
+    with realize_cache:
+        #
+        # check again cached_types, which might have been filled while
+        # we were waiting for the recursive lock
+        if from_ffi and ffi.cached_types[index] is not None:
+            return ffi.cached_types[index]
+
+        if realize_cache.rec_level > 1000:
+            raise oefmt(ffi.space.w_RuntimeError,
+                "type-building recursion too deep or infinite.  "
+                "This is known to occur e.g. in ``struct s { void(*callable)"
+                "(struct s); }''.  Please report if you get this error and "
+                "really need support for your case.")
         x = realize_c_type_or_func_now(ffi, op, opcodes, index)
-    finally:
-        realize_cache.rec_level -= 1
 
     if from_ffi:
         assert ffi.cached_types[index] is None or ffi.cached_types[index] is x
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to