From: Lisandro Dalcin Date: Tue, 3 Feb 2009 18:40:54 +0000 (-0200) Subject: enhancements to refnanny exception handling and API X-Git-Tag: 0.11.rc~93^2~8 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=0cc30e8578345eb8399f69ed5259cab9fe04b2b9;p=cython.git enhancements to refnanny exception handling and API --- diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py index c5ec83ee..4ce5d0e2 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 f3418bc8..f02d96b0 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 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(type, value, tb) + Py_INCREF(ctx) + return ctx + except: + Py_XDECREF(type) + Py_XDECREF(value) + Py_XDECREF(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: (ctx).regref(None, lineno, True) else: (ctx).regref(p_obj, lineno, False) - exc.PyErr_Restore(type, value, tb) + PyErr_Restore(type, value, tb) except: Py_XDECREF(type) Py_XDECREF(value) Py_XDECREF(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: (ctx).delref(None, lineno, True) else: (ctx).delref(p_obj, lineno, False) - exc.PyErr_Restore(type, value, tb) + PyErr_Restore(type, value, tb) except: Py_XDECREF(type) Py_XDECREF(value) Py_XDECREF(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(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(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 = 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(type, value, tb) - except Exception, e: + errors = (ctx[0]).end() + PyErr_Restore(type, value, tb) + except: Py_XDECREF(type) Py_XDECREF(value) Py_XDECREF(tb) raise finally: - Py_XDECREF(obj) + Py_XDECREF(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(&api, NULL)