[pypy-svn] r73156 - in pypy/trunk/pypy: interpreter module/_weakref module/_weakref/test

fijal at codespeak.net fijal at codespeak.net
Tue Mar 30 05:27:03 CEST 2010


Author: fijal
Date: Tue Mar 30 05:27:01 2010
New Revision: 73156

Modified:
   pypy/trunk/pypy/interpreter/executioncontext.py
   pypy/trunk/pypy/module/_weakref/interp__weakref.py
   pypy/trunk/pypy/module/_weakref/test/test_weakref.py
Log:
Try to kill segfault by fighting with uncontrolled calls of app level weakref
callback in the middle of compiling assembler (it could segfault pypy other
way, but this is the observed way).


Modified: pypy/trunk/pypy/interpreter/executioncontext.py
==============================================================================
--- pypy/trunk/pypy/interpreter/executioncontext.py	(original)
+++ pypy/trunk/pypy/interpreter/executioncontext.py	Tue Mar 30 05:27:01 2010
@@ -478,12 +478,17 @@
     def __init__(self, space):
         AsyncAction.__init__(self, space)
         self.dying_objects_w = []
+        self.weakrefs_w = []
         self.finalizers_lock_count = 0
 
     def register_dying_object(self, w_obj):
         self.dying_objects_w.append(w_obj)
         self.fire()
 
+    def register_weakref_callback(self, w_ref):
+        self.weakrefs_w.append(w_ref)
+        self.fire()
+
     def perform(self, executioncontext, frame):
         if self.finalizers_lock_count > 0:
             return
@@ -505,8 +510,16 @@
             # finally, this calls the interp-level destructor for the
             # cases where there is both an app-level and a built-in __del__.
             w_obj._call_builtin_destructor()
-
-
+        pending_w = self.weakrefs_w
+        self.weakrefs_w = []
+        for i in range(len(pending_w)):
+            w_ref = pending_w[i]
+            try:
+                w_ref.activate_callback()
+            except OperationError, e:
+                e.write_unraisable(space, 'weakref ', w_obj)
+                e.clear(space)   # break up reference cycles
+        
 class FrameTraceAction(AsyncAction):
     """An action that calls the local trace functions (w_f_trace)."""
 

Modified: pypy/trunk/pypy/module/_weakref/interp__weakref.py
==============================================================================
--- pypy/trunk/pypy/module/_weakref/interp__weakref.py	(original)
+++ pypy/trunk/pypy/module/_weakref/interp__weakref.py	Tue Mar 30 05:27:01 2010
@@ -23,7 +23,7 @@
         for i in range(len(self.refs_weak) - 1, -1, -1):
             w_ref = self.refs_weak[i]()
             if w_ref is not None:
-                w_ref.activate_callback()
+                self.space.user_del_action.register_weakref_callback(w_ref)
 
     def clear_all_weakrefs(self):
         """Clear all weakrefs.  This is called when an app-level object has

Modified: pypy/trunk/pypy/module/_weakref/test/test_weakref.py
==============================================================================
--- pypy/trunk/pypy/module/_weakref/test/test_weakref.py	(original)
+++ pypy/trunk/pypy/module/_weakref/test/test_weakref.py	Tue Mar 30 05:27:01 2010
@@ -411,3 +411,15 @@
 
         a = A()
         assert _weakref.ref(a) == a
+
+    def test_callback_raises(self):
+        import _weakref, gc
+        class A(object):
+            pass
+        a1 = A()
+        def callback(ref):
+            explode
+        ref1 = _weakref.ref(a1, callback)
+        del a1
+        gc.collect()
+        assert ref1() is None



More information about the Pypy-commit mailing list