diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py index c5ec83ee9963d688db00a1487e2297079c9ece12..4ce5d0e22c66f8b5cf8b2d5695a7ea9878fc7af2 100644 --- a/Cython/Compiler/ModuleNode.py +++ b/Cython/Compiler/ModuleNode.py @@ -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) diff --git a/Cython/Runtime/refnanny.pyx b/Cython/Runtime/refnanny.pyx index f3418bc85812b9ac6a53b1889bbab8a501a814bd..f02d96b07fa1d049ca9215e2de600798131c19c8 100644 --- a/Cython/Runtime/refnanny.pyx +++ b/Cython/Runtime/refnanny.pyx @@ -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)