Commit 0cc30e85 authored by Lisandro Dalcin's avatar Lisandro Dalcin

enhancements to refnanny exception handling and API

parent 503a314b
...@@ -2339,7 +2339,7 @@ typedef struct { ...@@ -2339,7 +2339,7 @@ typedef struct {
void (*GOTREF)(void*, PyObject*, int); void (*GOTREF)(void*, PyObject*, int);
void (*GIVEREF)(void*, PyObject*, int); void (*GIVEREF)(void*, PyObject*, int);
void* (*NewContext)(const char*, int); void* (*NewContext)(const char*, int);
int (*FinishContext)(void*); int (*FinishContext)(void**);
} __Pyx_RefnannyAPIStruct; } __Pyx_RefnannyAPIStruct;
static __Pyx_RefnannyAPIStruct* __Pyx_Refnanny = NULL; static __Pyx_RefnannyAPIStruct* __Pyx_Refnanny = NULL;
#define __Pyx_ImportRefcountAPI(name) \ #define __Pyx_ImportRefcountAPI(name) \
...@@ -2351,7 +2351,7 @@ static __Pyx_RefnannyAPIStruct* __Pyx_Refnanny = NULL; ...@@ -2351,7 +2351,7 @@ static __Pyx_RefnannyAPIStruct* __Pyx_Refnanny = NULL;
#define __Pyx_GIVEREF(r) __Pyx_Refnanny->GIVEREF(__pyx_refchk, (r), __LINE__) #define __Pyx_GIVEREF(r) __Pyx_Refnanny->GIVEREF(__pyx_refchk, (r), __LINE__)
#define __Pyx_SetupRefcountContext(name) \ #define __Pyx_SetupRefcountContext(name) \
void* __pyx_refchk = __Pyx_Refnanny->NewContext((name), __LINE__) 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 #else
#define __Pyx_INCREF(r) Py_INCREF(r) #define __Pyx_INCREF(r) Py_INCREF(r)
#define __Pyx_DECREF(r) Py_DECREF(r) #define __Pyx_DECREF(r) Py_DECREF(r)
......
from python_ref cimport Py_INCREF, Py_DECREF, Py_XDECREF 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 loglevel = 0
...@@ -51,89 +51,101 @@ class Context(object): ...@@ -51,89 +51,101 @@ class Context(object):
msg += "\n Acquired on lines: " + ", ".join(["%d" % x for x in linenos]) msg += "\n Acquired on lines: " + ", ".join(["%d" % x for x in linenos])
self.errors.append("References leaked: %s" % msg) self.errors.append("References leaked: %s" % msg)
if self.errors: if self.errors:
# print self.errors return "\n".join(self.errors)
raise Error("\n".join(self.errors)) else:
return None
cdef void* NewContext(char* funcname, int lineno) except NULL:
if exc.PyErr_Occurred() != NULL:
print "error flag set on newcontext?"
return NULL cdef PyObject* NewContext(char* funcname, int lineno) except NULL:
ctx = Context() cdef PyObject* type = NULL, *value = NULL, *tb = NULL
Py_INCREF(ctx) PyErr_Fetch(&type, &value, &tb)
return <void*>ctx try:
ctx = Context()
cdef void GOTREF(void* ctx, void* p_obj, int lineno): PyErr_Restore(<object>type, <object>value, <object>tb)
cdef exc.PyObject* type = NULL, *value = NULL, *tb = NULL 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 if ctx == NULL: return
exc.PyErr_Fetch(&type, &value, &tb) PyErr_Fetch(&type, &value, &tb)
try: try:
if p_obj is NULL: if p_obj is NULL:
(<object>ctx).regref(None, lineno, True) (<object>ctx).regref(None, lineno, True)
else: else:
(<object>ctx).regref(<object>p_obj, lineno, False) (<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: except:
Py_XDECREF(<object>type) Py_XDECREF(<object>type)
Py_XDECREF(<object>value) Py_XDECREF(<object>value)
Py_XDECREF(<object>tb) Py_XDECREF(<object>tb)
raise raise
cdef void GIVEREF(void* ctx, void* p_obj, int lineno): cdef void GIVEREF(PyObject* ctx, PyObject* p_obj, int lineno):
cdef exc.PyObject* type = NULL, *value = NULL, *tb = NULL cdef PyObject* type = NULL, *value = NULL, *tb = NULL
if ctx == NULL: return if ctx == NULL: return
exc.PyErr_Fetch(&type, &value, &tb) PyErr_Fetch(&type, &value, &tb)
try: try:
if p_obj is NULL: if p_obj is NULL:
(<object>ctx).delref(None, lineno, True) (<object>ctx).delref(None, lineno, True)
else: else:
(<object>ctx).delref(<object>p_obj, lineno, False) (<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: except:
Py_XDECREF(<object>type) Py_XDECREF(<object>type)
Py_XDECREF(<object>value) Py_XDECREF(<object>value)
Py_XDECREF(<object>tb) Py_XDECREF(<object>tb)
raise 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) if obj is not NULL: Py_INCREF(<object>obj)
GOTREF(ctx, obj, lineno) 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 raises exception if we hit 0
GIVEREF(ctx, obj, lineno) GIVEREF(ctx, obj, lineno)
if obj is not NULL: Py_DECREF(<object>obj) if obj is not NULL: Py_DECREF(<object>obj)
cdef int FinishContext(void* ctx) except -1: cdef int FinishContext(PyObject** ctx) except -1:
cdef exc.PyObject* type = NULL, *value = NULL, *tb = NULL cdef PyObject* type = NULL, *value = NULL, *tb = NULL
if ctx == NULL: if ctx == NULL: assert False
assert False if ctx[0] == NULL: assert False # XXX What to do here?
exc.PyErr_Fetch(&type, &value, &tb) cdef object errors = None
obj = <object>ctx PyErr_Fetch(&type, &value, &tb)
try: try:
obj.end() errors = (<object>ctx[0]).end()
exc.PyErr_Restore(<object>type, <object>value, <object>tb) PyErr_Restore(<object>type, <object>value, <object>tb)
except Exception, e: except:
Py_XDECREF(<object>type) Py_XDECREF(<object>type)
Py_XDECREF(<object>value) Py_XDECREF(<object>value)
Py_XDECREF(<object>tb) Py_XDECREF(<object>tb)
raise raise
finally: finally:
Py_XDECREF(obj) Py_XDECREF(<object>ctx[0])
ctx[0] = NULL
if errors:
raise Error(errors)
return 0 return 0
cdef extern from "Python.h": cdef extern from "Python.h":
object PyCObject_FromVoidPtr(void *, void (*)(void*)) object PyCObject_FromVoidPtr(void*, void (*)(void*))
ctypedef struct RefnannyAPIStruct: ctypedef struct RefnannyAPIStruct:
void (*INCREF)(void*, void*, int) void (*INCREF)(PyObject*, PyObject*, int)
void (*DECREF)(void*, void*, int) void (*DECREF)(PyObject*, PyObject*, int)
void (*GOTREF)(void*, void*, int) void (*GOTREF)(PyObject*, PyObject*, int)
void (*GIVEREF)(void*, void*, int) void (*GIVEREF)(PyObject*, PyObject*, int)
void* (*NewContext)(char*, int) except NULL PyObject* (*NewContext)(char*, int) except NULL
int (*FinishContext)(void*) except -1 int (*FinishContext)(PyObject**) except -1
cdef RefnannyAPIStruct api cdef RefnannyAPIStruct api
api.INCREF = INCREF api.INCREF = INCREF
...@@ -143,4 +155,4 @@ api.GIVEREF = GIVEREF ...@@ -143,4 +155,4 @@ api.GIVEREF = GIVEREF
api.NewContext = NewContext api.NewContext = NewContext
api.FinishContext = FinishContext api.FinishContext = FinishContext
RefnannyAPI = PyCObject_FromVoidPtr(&api, NULL) RefnannyAPI = PyCObject_FromVoidPtr(<void*>&api, NULL)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment