enhancements to refnanny exception handling and API
authorLisandro Dalcin <dalcinl@gmail.com>
Tue, 3 Feb 2009 18:40:54 +0000 (16:40 -0200)
committerLisandro Dalcin <dalcinl@gmail.com>
Tue, 3 Feb 2009 18:40:54 +0000 (16:40 -0200)
Cython/Compiler/ModuleNode.py
Cython/Runtime/refnanny.pyx

index c5ec83ee9963d688db00a1487e2297079c9ece12..4ce5d0e22c66f8b5cf8b2d5695a7ea9878fc7af2 100644 (file)
@@ -2339,7 +2339,7 @@ typedef struct {
   void (*GOTREF)(void*, PyObject*, int);
   void (*GIVEREF)(void*, PyObject*, int);
   void* (*NewContext)(const char*, int);
-  int (*FinishContext)(void*);
+  int (*FinishContext)(void**);
 } __Pyx_RefnannyAPIStruct;
 static __Pyx_RefnannyAPIStruct* __Pyx_Refnanny = NULL;
 #define __Pyx_ImportRefcountAPI(name) \
@@ -2351,7 +2351,7 @@ static __Pyx_RefnannyAPIStruct* __Pyx_Refnanny = NULL;
 #define __Pyx_GIVEREF(r) __Pyx_Refnanny->GIVEREF(__pyx_refchk, (r), __LINE__)
 #define __Pyx_SetupRefcountContext(name) \
   void* __pyx_refchk = __Pyx_Refnanny->NewContext((name), __LINE__)
-#define __Pyx_FinishRefcountContext() __Pyx_Refnanny->FinishContext(__pyx_refchk)
+#define __Pyx_FinishRefcountContext() __Pyx_Refnanny->FinishContext(&__pyx_refchk)
 #else
 #define __Pyx_INCREF(r) Py_INCREF(r)
 #define __Pyx_DECREF(r) Py_DECREF(r)
index f3418bc85812b9ac6a53b1889bbab8a501a814bd..f02d96b07fa1d049ca9215e2de600798131c19c8 100644 (file)
@@ -1,5 +1,5 @@
 from python_ref cimport Py_INCREF, Py_DECREF, Py_XDECREF
-cimport python_exc as exc
+from python_exc cimport PyObject, PyErr_Fetch, PyErr_Restore
 
 
 loglevel = 0
@@ -51,89 +51,101 @@ class Context(object):
                 msg += "\n  Acquired on lines: " + ", ".join(["%d" % x for x in linenos])
             self.errors.append("References leaked: %s" % msg)
         if self.errors:
-#            print self.errors
-            raise Error("\n".join(self.errors))
-
-cdef void* NewContext(char* funcname, int lineno) except NULL:
-    if exc.PyErr_Occurred() != NULL:
-        print "error flag set on newcontext?"
-        return NULL
-    ctx = Context()
-    Py_INCREF(ctx)
-    return <void*>ctx
-
-cdef void GOTREF(void* ctx, void* p_obj, int lineno):
-    cdef exc.PyObject* type = NULL, *value = NULL, *tb = NULL
+            return "\n".join(self.errors)
+        else:
+            return None
+
+
+
+cdef PyObject* NewContext(char* funcname, int lineno) except NULL:
+    cdef PyObject* type = NULL, *value = NULL, *tb = NULL
+    PyErr_Fetch(&type, &value, &tb)
+    try:
+        ctx = Context()
+        PyErr_Restore(<object>type, <object>value, <object>tb)
+        Py_INCREF(ctx)
+        return <PyObject*>ctx
+    except:
+        Py_XDECREF(<object>type)
+        Py_XDECREF(<object>value)
+        Py_XDECREF(<object>tb)
+        raise
+
+cdef void GOTREF(PyObject* ctx, PyObject* p_obj, int lineno):
+    cdef PyObject* type = NULL, *value = NULL, *tb = NULL
     if ctx == NULL: return
-    exc.PyErr_Fetch(&type, &value, &tb)
+    PyErr_Fetch(&type, &value, &tb)
     try:
         if p_obj is NULL:
             (<object>ctx).regref(None, lineno, True)
         else:
             (<object>ctx).regref(<object>p_obj, lineno, False)
-        exc.PyErr_Restore(<object>type, <object>value, <object>tb)
+        PyErr_Restore(<object>type, <object>value, <object>tb)
     except:
         Py_XDECREF(<object>type)
         Py_XDECREF(<object>value)
         Py_XDECREF(<object>tb)
         raise
 
-cdef void GIVEREF(void* ctx, void* p_obj, int lineno):
-    cdef exc.PyObject* type = NULL, *value = NULL, *tb = NULL
+cdef void GIVEREF(PyObject* ctx, PyObject* p_obj, int lineno):
+    cdef PyObject* type = NULL, *value = NULL, *tb = NULL
     if ctx == NULL: return
-    exc.PyErr_Fetch(&type, &value, &tb)
+    PyErr_Fetch(&type, &value, &tb)
     try:
         if p_obj is NULL:
             (<object>ctx).delref(None, lineno, True)
         else:
             (<object>ctx).delref(<object>p_obj, lineno, False)
-        exc.PyErr_Restore(<object>type, <object>value, <object>tb)
+        PyErr_Restore(<object>type, <object>value, <object>tb)
     except:
         Py_XDECREF(<object>type)
         Py_XDECREF(<object>value)
         Py_XDECREF(<object>tb)
         raise
 
-cdef void INCREF(void* ctx, void* obj, int lineno):
+cdef void INCREF(PyObject* ctx, PyObject* obj, int lineno):
     if obj is not NULL: Py_INCREF(<object>obj)
     GOTREF(ctx, obj, lineno)
 
-cdef void DECREF(void* ctx, void* obj, int lineno):
+cdef void DECREF(PyObject* ctx, PyObject* obj, int lineno):
     # GIVEREF raises exception if we hit 0
     GIVEREF(ctx, obj, lineno)
     if obj is not NULL: Py_DECREF(<object>obj)
 
-cdef int FinishContext(void* ctx) except -1:
-    cdef exc.PyObject* type = NULL, *value = NULL, *tb = NULL
-    if ctx == NULL:
-        assert False
-    exc.PyErr_Fetch(&type, &value, &tb)
-    obj = <object>ctx
+cdef int FinishContext(PyObject** ctx) except -1:
+    cdef PyObject* type = NULL, *value = NULL, *tb = NULL
+    if ctx == NULL: assert False
+    if ctx[0] == NULL: assert False # XXX What to do here?
+    cdef object errors = None
+    PyErr_Fetch(&type, &value, &tb)
     try:
-        obj.end()
-        exc.PyErr_Restore(<object>type, <object>value, <object>tb)
-    except Exception, e:
+        errors = (<object>ctx[0]).end()
+        PyErr_Restore(<object>type, <object>value, <object>tb)
+    except:
         Py_XDECREF(<object>type)
         Py_XDECREF(<object>value)
         Py_XDECREF(<object>tb)
         raise
     finally:
-        Py_XDECREF(obj)
+        Py_XDECREF(<object>ctx[0])
+        ctx[0] = NULL
+    if errors:
+        raise Error(errors)
     return 0
 
 
 
 
 cdef extern from "Python.h":
-    object PyCObject_FromVoidPtr(void *, void (*)(void*))
+    object PyCObject_FromVoidPtr(void*, void (*)(void*))
 
 ctypedef struct RefnannyAPIStruct:
-  void (*INCREF)(void*, void*, int)
-  void (*DECREF)(void*, void*, int)
-  void (*GOTREF)(void*, void*, int)
-  void (*GIVEREF)(void*, void*, int)
-  void* (*NewContext)(char*, int) except NULL
-  int (*FinishContext)(void*) except -1
+  void (*INCREF)(PyObject*, PyObject*, int)
+  void (*DECREF)(PyObject*, PyObject*, int)
+  void (*GOTREF)(PyObject*, PyObject*, int)
+  void (*GIVEREF)(PyObject*, PyObject*, int)
+  PyObject* (*NewContext)(char*, int) except NULL
+  int (*FinishContext)(PyObject**) except -1
 
 cdef RefnannyAPIStruct api
 api.INCREF = INCREF
@@ -143,4 +155,4 @@ api.GIVEREF = GIVEREF
 api.NewContext = NewContext
 api.FinishContext = FinishContext
 
-RefnannyAPI = PyCObject_FromVoidPtr(&api, NULL)
+RefnannyAPI = PyCObject_FromVoidPtr(<void*>&api, NULL)