Commit 749e1bfb authored by Dag Sverre Seljebotn's avatar Dag Sverre Seljebotn

refnanny: Cleanup + fix some smaller issues

parent 30867450
...@@ -33,19 +33,23 @@ class Context(object): ...@@ -33,19 +33,23 @@ class Context(object):
linenumbers.append(lineno) linenumbers.append(lineno)
def delref(self, obj, lineno, is_null): def delref(self, obj, lineno, is_null):
# returns whether it is ok to do the decref operation
log(LOG_ALL, u'delref', u"<NULL>" if is_null else obj, lineno) log(LOG_ALL, u'delref', u"<NULL>" if is_null else obj, lineno)
if is_null: if is_null:
self.errors.append(u"NULL argument on line %d" % lineno) self.errors.append(u"NULL argument on line %d" % lineno)
return return False
id_ = id(obj) id_ = id(obj)
count, linenumbers = self.refs.get(id_, (0, [])) count, linenumbers = self.refs.get(id_, (0, []))
if count == 0: if count == 0:
self.errors.append(u"Too many decrefs on line %d, reference acquired on lines %r" % self.errors.append(u"Too many decrefs on line %d, reference acquired on lines %r" %
(lineno, linenumbers)) (lineno, linenumbers))
return False
elif count == 1: elif count == 1:
del self.refs[id_] del self.refs[id_]
return True
else: else:
self.refs[id_] = (count - 1, linenumbers) self.refs[id_] = (count - 1, linenumbers)
return True
def end(self): def end(self):
if len(self.refs) > 0: if len(self.refs) > 0:
...@@ -58,21 +62,28 @@ class Context(object): ...@@ -58,21 +62,28 @@ class Context(object):
else: else:
return None return None
def report_unraisable(e):
try:
print "refnanny raised an exception: %s" % e
except:
pass # We absolutely cannot exit with an exception
# All Python operations must happen after any existing
# exception has been fetched, in case we are called from
# exception-handling code.
cdef PyObject* NewContext(char* funcname, int lineno, char* filename) except NULL: cdef PyObject* NewContext(char* funcname, int lineno, char* filename) except NULL:
cdef PyObject* type = NULL, *value = NULL, *tb = NULL cdef PyObject* type = NULL, *value = NULL, *tb = NULL
cdef PyObject* result = NULL
PyErr_Fetch(&type, &value, &tb) PyErr_Fetch(&type, &value, &tb)
try: try:
ctx = Context(funcname, lineno, filename) ctx = Context(funcname, lineno, filename)
PyErr_Restore(<object>type, <object>value, <object>tb)
Py_INCREF(ctx) Py_INCREF(ctx)
return <PyObject*>ctx result = <PyObject*>ctx
except: except Exception, e:
Py_XDECREF(<object>type) report_unraisable(e)
Py_XDECREF(<object>value) PyErr_Restore(<object>type, <object>value, <object>tb)
Py_XDECREF(<object>tb) return result
raise
cdef void GOTREF(PyObject* ctx, PyObject* p_obj, int lineno): cdef void GOTREF(PyObject* ctx, PyObject* p_obj, int lineno):
cdef PyObject* type = NULL, *value = NULL, *tb = NULL cdef PyObject* type = NULL, *value = NULL, *tb = NULL
...@@ -83,58 +94,54 @@ cdef void GOTREF(PyObject* ctx, PyObject* p_obj, int lineno): ...@@ -83,58 +94,54 @@ cdef void GOTREF(PyObject* ctx, PyObject* p_obj, int lineno):
(<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)
PyErr_Restore(<object>type, <object>value, <object>tb) except Exception, e:
except: report_unraisable(e)
Py_XDECREF(<object>type) PyErr_Restore(<object>type, <object>value, <object>tb)
Py_XDECREF(<object>value)
Py_XDECREF(<object>tb)
raise
cdef void GIVEREF(PyObject* ctx, PyObject* p_obj, int lineno): cdef int GIVEREF_and_report(PyObject* ctx, PyObject* p_obj, int lineno):
cdef PyObject* type = NULL, *value = NULL, *tb = NULL cdef PyObject* type = NULL, *value = NULL, *tb = NULL
if ctx == NULL: return cdef bint decref_ok = False
PyErr_Fetch(&type, &value, &tb) PyErr_Fetch(&type, &value, &tb)
try: try:
assert ctx is not NULL, "ctx us NULL"
if p_obj is NULL: if p_obj is NULL:
(<object>ctx).delref(None, lineno, True) decref_ok = (<object>ctx).delref(None, lineno, True)
else: else:
(<object>ctx).delref(<object>p_obj, lineno, False) decref_ok = (<object>ctx).delref(<object>p_obj, lineno, False)
PyErr_Restore(<object>type, <object>value, <object>tb) except Exception, e:
except: report_unraisable(e)
Py_XDECREF(<object>type) PyErr_Restore(<object>type, <object>value, <object>tb)
Py_XDECREF(<object>value) return decref_ok
Py_XDECREF(<object>tb)
raise cdef void GIVEREF(PyObject* ctx, PyObject* p_obj, int lineno):
GIVEREF_and_report(ctx, p_obj, lineno)
cdef void INCREF(PyObject* ctx, PyObject* 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(PyObject* ctx, PyObject* obj, int lineno): cdef void DECREF(PyObject* ctx, PyObject* obj, int lineno):
# GIVEREF raises exception if we hit 0 if GIVEREF_and_report(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 void FinishContext(PyObject** ctx): cdef void FinishContext(PyObject** ctx):
cdef PyObject* type = NULL, *value = NULL, *tb = NULL 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 cdef object errors = None
PyErr_Fetch(&type, &value, &tb) PyErr_Fetch(&type, &value, &tb)
try: try:
if ctx == NULL: assert False, "ctx is NULL"
if ctx[0] == NULL: assert False, "ctx[0] is NULL"
errors = (<object>ctx[0]).end() errors = (<object>ctx[0]).end()
pos = (<object>ctx[0]).filename, (<object>ctx[0]).name pos = (<object>ctx[0]).filename, (<object>ctx[0]).name
if errors: if errors:
print u"%s: %s()" % pos print u"%s: %s()" % pos
print errors # raise Error(errors) print errors # raise Error(errors)
PyErr_Restore(<object>type, <object>value, <object>tb) except Exception, e:
except: report_unraisable(e)
Py_XDECREF(<object>type) Py_XDECREF(<object>ctx[0])
Py_XDECREF(<object>value) ctx[0] = NULL
Py_XDECREF(<object>tb) PyErr_Restore(<object>type, <object>value, <object>tb)
finally:
Py_XDECREF(<object>ctx[0])
ctx[0] = NULL
cdef extern from "Python.h": cdef extern from "Python.h":
object PyCObject_FromVoidPtr(void*, void (*)(void*)) object PyCObject_FromVoidPtr(void*, void (*)(void*))
......
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