Commit a4b2bc70 authored by Victor Stinner's avatar Victor Stinner Committed by GitHub

bpo-9263: Use _PyObject_ASSERT() in gcmodule.c (GH-10112)

Replace assert() with _PyObject_ASSERT() in Modules/gcmodule.c
to dump the faulty object on assertion failure to ease debugging.

Fix also indentation of a large comment.

Initial patch written by David Malcolm.
Co-Authored-By: default avatarDavid Malcolm <dmalcolm@redhat.com>
parent 24702044
...@@ -366,7 +366,7 @@ update_refs(PyGC_Head *containers) ...@@ -366,7 +366,7 @@ update_refs(PyGC_Head *containers)
* so serious that maybe this should be a release-build * so serious that maybe this should be a release-build
* check instead of an assert? * check instead of an assert?
*/ */
assert(gc_get_refs(gc) != 0); _PyObject_ASSERT(FROM_GC(gc), gc_get_refs(gc) != 0);
} }
} }
...@@ -432,8 +432,10 @@ visit_reachable(PyObject *op, PyGC_Head *reachable) ...@@ -432,8 +432,10 @@ visit_reachable(PyObject *op, PyGC_Head *reachable)
// Manually unlink gc from unreachable list because // Manually unlink gc from unreachable list because
PyGC_Head *prev = GC_PREV(gc); PyGC_Head *prev = GC_PREV(gc);
PyGC_Head *next = (PyGC_Head*)(gc->_gc_next & ~NEXT_MASK_UNREACHABLE); PyGC_Head *next = (PyGC_Head*)(gc->_gc_next & ~NEXT_MASK_UNREACHABLE);
assert(prev->_gc_next & NEXT_MASK_UNREACHABLE); _PyObject_ASSERT(FROM_GC(prev),
assert(next->_gc_next & NEXT_MASK_UNREACHABLE); prev->_gc_next & NEXT_MASK_UNREACHABLE);
_PyObject_ASSERT(FROM_GC(next),
next->_gc_next & NEXT_MASK_UNREACHABLE);
prev->_gc_next = gc->_gc_next; // copy NEXT_MASK_UNREACHABLE prev->_gc_next = gc->_gc_next; // copy NEXT_MASK_UNREACHABLE
_PyGCHead_SET_PREV(next, prev); _PyGCHead_SET_PREV(next, prev);
...@@ -453,7 +455,7 @@ visit_reachable(PyObject *op, PyGC_Head *reachable) ...@@ -453,7 +455,7 @@ visit_reachable(PyObject *op, PyGC_Head *reachable)
* list, and move_unreachable will eventually get to it. * list, and move_unreachable will eventually get to it.
*/ */
else { else {
assert(gc_refs > 0); _PyObject_ASSERT_WITH_MSG(op, gc_refs > 0, "refcount is too small");
} }
return 0; return 0;
} }
...@@ -498,7 +500,8 @@ move_unreachable(PyGC_Head *young, PyGC_Head *unreachable) ...@@ -498,7 +500,8 @@ move_unreachable(PyGC_Head *young, PyGC_Head *unreachable)
*/ */
PyObject *op = FROM_GC(gc); PyObject *op = FROM_GC(gc);
traverseproc traverse = Py_TYPE(op)->tp_traverse; traverseproc traverse = Py_TYPE(op)->tp_traverse;
assert(gc_get_refs(gc) > 0); _PyObject_ASSERT_WITH_MSG(op, gc_get_refs(gc) > 0,
"refcount is too small");
// NOTE: visit_reachable may change gc->_gc_next when // NOTE: visit_reachable may change gc->_gc_next when
// young->_gc_prev == gc. Don't do gc = GC_NEXT(gc) before! // young->_gc_prev == gc. Don't do gc = GC_NEXT(gc) before!
(void) traverse(op, (void) traverse(op,
...@@ -593,7 +596,7 @@ move_legacy_finalizers(PyGC_Head *unreachable, PyGC_Head *finalizers) ...@@ -593,7 +596,7 @@ move_legacy_finalizers(PyGC_Head *unreachable, PyGC_Head *finalizers)
for (gc = GC_NEXT(unreachable); gc != unreachable; gc = next) { for (gc = GC_NEXT(unreachable); gc != unreachable; gc = next) {
PyObject *op = FROM_GC(gc); PyObject *op = FROM_GC(gc);
assert(gc->_gc_next & NEXT_MASK_UNREACHABLE); _PyObject_ASSERT(op, gc->_gc_next & NEXT_MASK_UNREACHABLE);
gc->_gc_next &= ~NEXT_MASK_UNREACHABLE; gc->_gc_next &= ~NEXT_MASK_UNREACHABLE;
next = (PyGC_Head*)gc->_gc_next; next = (PyGC_Head*)gc->_gc_next;
...@@ -690,11 +693,13 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old) ...@@ -690,11 +693,13 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old)
* the callback pointer intact. Obscure: it also * the callback pointer intact. Obscure: it also
* changes *wrlist. * changes *wrlist.
*/ */
assert(wr->wr_object == op); _PyObject_ASSERT((PyObject *)wr, wr->wr_object == op);
_PyWeakref_ClearRef(wr); _PyWeakref_ClearRef(wr);
assert(wr->wr_object == Py_None); _PyObject_ASSERT((PyObject *)wr, wr->wr_object == Py_None);
if (wr->wr_callback == NULL) if (wr->wr_callback == NULL) {
continue; /* no callback */ /* no callback */
continue;
}
/* Headache time. `op` is going away, and is weakly referenced by /* Headache time. `op` is going away, and is weakly referenced by
* `wr`, which has a callback. Should the callback be invoked? If wr * `wr`, which has a callback. Should the callback be invoked? If wr
...@@ -751,10 +756,10 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old) ...@@ -751,10 +756,10 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old)
gc = (PyGC_Head*)wrcb_to_call._gc_next; gc = (PyGC_Head*)wrcb_to_call._gc_next;
op = FROM_GC(gc); op = FROM_GC(gc);
assert(PyWeakref_Check(op)); _PyObject_ASSERT(op, PyWeakref_Check(op));
wr = (PyWeakReference *)op; wr = (PyWeakReference *)op;
callback = wr->wr_callback; callback = wr->wr_callback;
assert(callback != NULL); _PyObject_ASSERT(op, callback != NULL);
/* copy-paste of weakrefobject.c's handle_callback() */ /* copy-paste of weakrefobject.c's handle_callback() */
temp = PyObject_CallFunctionObjArgs(callback, wr, NULL); temp = PyObject_CallFunctionObjArgs(callback, wr, NULL);
...@@ -874,12 +879,14 @@ check_garbage(PyGC_Head *collectable) ...@@ -874,12 +879,14 @@ check_garbage(PyGC_Head *collectable)
for (gc = GC_NEXT(collectable); gc != collectable; gc = GC_NEXT(gc)) { for (gc = GC_NEXT(collectable); gc != collectable; gc = GC_NEXT(gc)) {
// Use gc_refs and break gc_prev again. // Use gc_refs and break gc_prev again.
gc_set_refs(gc, Py_REFCNT(FROM_GC(gc))); gc_set_refs(gc, Py_REFCNT(FROM_GC(gc)));
assert(gc_get_refs(gc) != 0); _PyObject_ASSERT(FROM_GC(gc), gc_get_refs(gc) != 0);
} }
subtract_refs(collectable); subtract_refs(collectable);
PyGC_Head *prev = collectable; PyGC_Head *prev = collectable;
for (gc = GC_NEXT(collectable); gc != collectable; gc = GC_NEXT(gc)) { for (gc = GC_NEXT(collectable); gc != collectable; gc = GC_NEXT(gc)) {
assert(gc_get_refs(gc) >= 0); _PyObject_ASSERT_WITH_MSG(FROM_GC(gc),
gc_get_refs(gc) >= 0,
"refcount is too small");
if (gc_get_refs(gc) != 0) { if (gc_get_refs(gc) != 0) {
ret = -1; ret = -1;
} }
...@@ -905,7 +912,8 @@ delete_garbage(PyGC_Head *collectable, PyGC_Head *old) ...@@ -905,7 +912,8 @@ delete_garbage(PyGC_Head *collectable, PyGC_Head *old)
PyGC_Head *gc = GC_NEXT(collectable); PyGC_Head *gc = GC_NEXT(collectable);
PyObject *op = FROM_GC(gc); PyObject *op = FROM_GC(gc);
assert(Py_REFCNT(FROM_GC(gc)) > 0); _PyObject_ASSERT_WITH_MSG(op, Py_REFCNT(op) > 0,
"refcount is too small");
if (_PyRuntime.gc.debug & DEBUG_SAVEALL) { if (_PyRuntime.gc.debug & DEBUG_SAVEALL) {
assert(_PyRuntime.gc.garbage != NULL); assert(_PyRuntime.gc.garbage != NULL);
...@@ -1933,10 +1941,12 @@ PyVarObject * ...@@ -1933,10 +1941,12 @@ PyVarObject *
_PyObject_GC_Resize(PyVarObject *op, Py_ssize_t nitems) _PyObject_GC_Resize(PyVarObject *op, Py_ssize_t nitems)
{ {
const size_t basicsize = _PyObject_VAR_SIZE(Py_TYPE(op), nitems); const size_t basicsize = _PyObject_VAR_SIZE(Py_TYPE(op), nitems);
PyGC_Head *g = AS_GC(op); _PyObject_ASSERT((PyObject *)op, !_PyObject_GC_IS_TRACKED(op));
assert(!_PyObject_GC_IS_TRACKED(op)); if (basicsize > PY_SSIZE_T_MAX - sizeof(PyGC_Head)) {
if (basicsize > PY_SSIZE_T_MAX - sizeof(PyGC_Head))
return (PyVarObject *)PyErr_NoMemory(); return (PyVarObject *)PyErr_NoMemory();
}
PyGC_Head *g = AS_GC(op);
g = (PyGC_Head *)PyObject_REALLOC(g, sizeof(PyGC_Head) + basicsize); g = (PyGC_Head *)PyObject_REALLOC(g, sizeof(PyGC_Head) + basicsize);
if (g == NULL) if (g == NULL)
return (PyVarObject *)PyErr_NoMemory(); return (PyVarObject *)PyErr_NoMemory();
......
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