[pypy-svn] r72976 - pypy/branch/cpython-extension/pypy/module/cpyext

xoraxax at codespeak.net xoraxax at codespeak.net
Sat Mar 27 21:40:14 CET 2010


Author: xoraxax
Date: Sat Mar 27 21:40:12 2010
New Revision: 72976

Modified:
   pypy/branch/cpython-extension/pypy/module/cpyext/api.py
   pypy/branch/cpython-extension/pypy/module/cpyext/pyerrors.py
   pypy/branch/cpython-extension/pypy/module/cpyext/state.py
Log:
Introduce correct refcount handling for (borrowed) exceptions.

Modified: pypy/branch/cpython-extension/pypy/module/cpyext/api.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/api.py	(original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/api.py	Sat Mar 27 21:40:12 2010
@@ -136,10 +136,12 @@
                         raise
                     state = space.fromcache(State)
                     e.normalize_exception(space)
-                    state.exc_type = e.w_type
-                    state.exc_value = e.get_w_value(space)
+                    state.set_exception(e.w_type, e.get_w_value(space))
                     return api_function.error_value
             finally:
+                if api_function.borrowed:
+                    state = space.fromcache(State)
+                    state.last_container = 0
                 from pypy.module.cpyext.macros import Py_DECREF
                 for arg in to_decref:
                     Py_DECREF(space, arg)
@@ -322,7 +324,10 @@
 @cpython_api([PyObject], lltype.Void, external=False)
 def register_container(space, container):
     state = space.fromcache(State)
-    container_ptr = rffi.cast(ADDR, container)
+    if not container: # self-managed
+        container_ptr = -1
+    else:
+        container_ptr = rffi.cast(ADDR, container)
     assert not state.last_container, "Last container was not fetched"
     state.last_container = container_ptr
 
@@ -332,6 +337,8 @@
     state.last_container = 0
     if not container_ptr:
         raise NullPointerException
+    if container_ptr == -1:
+        return
     borrowees = state.borrow_mapping.get(container_ptr)
     if borrowees is None:
         state.borrow_mapping[container_ptr] = borrowees = {}
@@ -371,12 +378,10 @@
         except OperationError, e:
             failed = True
             e.normalize_exception(space)
-            state.exc_type = e.w_type
-            state.exc_value = e.get_w_value(space)
+            state.set_exception(e.w_type, e.get_w_value(space))
         except BaseException, e:
             failed = True
-            state.exc_type = space.w_SystemError
-            state.exc_value = space.wrap(str(e))
+            state.set_exception(space.w_SystemError, space.wrap(str(e)))
             import traceback
             traceback.print_exc()
         else:

Modified: pypy/branch/cpython-extension/pypy/module/cpyext/pyerrors.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/pyerrors.py	(original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/pyerrors.py	Sat Mar 27 21:40:12 2010
@@ -1,25 +1,25 @@
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.interpreter.error import OperationError
-from pypy.module.cpyext.api import cpython_api, PyObject, make_ref
+from pypy.module.cpyext.api import cpython_api, PyObject, make_ref,\
+        register_container
 from pypy.module.cpyext.state import State
 
 @cpython_api([PyObject, rffi.CCHARP], lltype.Void)
 def PyErr_SetString(space, w_type, message_ptr):
     message = rffi.charp2str(message_ptr)
     state = space.fromcache(State)
-    state.exc_type = w_type
-    state.exc_value = space.call_function(w_type, space.wrap(message))
+    state.set_exception(w_type, space.wrap(message))
 
- at cpython_api([], PyObject)
+ at cpython_api([], PyObject, borrowed=True)
 def PyErr_Occurred(space):
     state = space.fromcache(State)
+    register_container(space, None)
     return state.exc_value
 
 @cpython_api([], lltype.Void)
 def PyErr_Clear(space):
     state = space.fromcache(State)
-    state.exc_type = None
-    state.exc_value = None
+    state.clear_exception()
 
 @cpython_api([], lltype.Void)
 def PyErr_BadInternalCall(space):

Modified: pypy/branch/cpython-extension/pypy/module/cpyext/state.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/state.py	(original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/state.py	Sat Mar 27 21:40:12 2010
@@ -1,4 +1,5 @@
 from pypy.rlib.objectmodel import we_are_translated
+from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.lib.identity_dict import identity_dict
 from pypy.interpreter.error import OperationError
 from pypy.rpython.lltypesystem import lltype
@@ -19,12 +20,29 @@
         self.exc_type = None
         self.exc_value = None
 
+    def set_exception(self, w_type, w_value):
+        self.clear_exception()
+        self.exc_type = w_type
+        self.exc_value = w_value
+
+    def clear_exception(self):
+        from pypy.module.cpyext.macros import Py_DECREF
+        from pypy.module.cpyext.api import make_ref, ADDR
+        # handling of borrowed objects, remove when we have
+        # a weakkeydict
+        exc_value = make_ref(self.space, self.exc_value, borrowed=True)
+        if exc_value:
+            Py_DECREF(self.space, exc_value)
+            containee_ptr = rffi.cast(ADDR, exc_value)
+            del self.borrowed_objects[containee_ptr]
+        self.exc_type = None
+        self.exc_value = None
+
     def check_and_raise_exception(self):
         exc_value = self.exc_value
         exc_type = self.exc_type
         if exc_type is not None or exc_value is not None:
-            self.exc_value = None
-            self.exc_type = None
+            self.clear_exception()
             op_err = OperationError(exc_type, exc_value)
             raise op_err
 



More information about the Pypy-commit mailing list