diff options
author | Victor Stinner <vstinner@redhat.com> | 2018-10-25 15:31:10 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-10-25 15:31:10 (GMT) |
commit | 626bff856840f471e98ec627043f780c111a063d (patch) | |
tree | 4c8f4da76f3443157e7a06a96d88bbc631650f88 /Modules | |
parent | 18618e652c56e61a134e596b315a13c7cb997a89 (diff) | |
download | cpython-626bff856840f471e98ec627043f780c111a063d.zip cpython-626bff856840f471e98ec627043f780c111a063d.tar.gz cpython-626bff856840f471e98ec627043f780c111a063d.tar.bz2 |
bpo-9263: Dump Python object on GC assertion failure (GH-10062)
Changes:
* Add _PyObject_AssertFailed() function.
* Add _PyObject_ASSERT() and _PyObject_ASSERT_WITH_MSG() macros.
* gc_decref(): replace assert() with _PyObject_ASSERT_WITH_MSG() to
dump the faulty object if the assertion fails.
_PyObject_AssertFailed() calls:
* _PyMem_DumpTraceback(): try to log the traceback where the object
memory has been allocated if tracemalloc is enabled.
* _PyObject_Dump(): log repr(obj).
* Py_FatalError(): log the current Python traceback.
_PyObject_AssertFailed() uses _PyObject_IsFreed() heuristic to check
if the object memory has been freed by a debug hook on Python memory
allocators.
Initial patch written by David Malcolm.
Co-Authored-By: David Malcolm <dmalcolm@redhat.com>
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_tracemalloc.c | 6 | ||||
-rw-r--r-- | Modules/gcmodule.c | 16 |
2 files changed, 13 insertions, 9 deletions
diff --git a/Modules/_tracemalloc.c b/Modules/_tracemalloc.c index d736b24..1005f2e 100644 --- a/Modules/_tracemalloc.c +++ b/Modules/_tracemalloc.c @@ -1436,10 +1436,12 @@ _tracemalloc__get_object_traceback(PyObject *module, PyObject *obj) traceback_t *traceback; type = Py_TYPE(obj); - if (PyType_IS_GC(type)) + if (PyType_IS_GC(type)) { ptr = (void *)((char *)obj - sizeof(PyGC_Head)); - else + } + else { ptr = (void *)obj; + } traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (uintptr_t)ptr); if (traceback == NULL) diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 7cddaba..2e19fe4 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -62,6 +62,12 @@ module gc // most gc_list_* functions for it. #define NEXT_MASK_UNREACHABLE (1) +/* Get an object's GC head */ +#define AS_GC(o) ((PyGC_Head *)(o)-1) + +/* Get the object given the GC head */ +#define FROM_GC(g) ((PyObject *)(((PyGC_Head *)g)+1)) + static inline int gc_is_collecting(PyGC_Head *g) { @@ -98,16 +104,12 @@ gc_reset_refs(PyGC_Head *g, Py_ssize_t refs) static inline void gc_decref(PyGC_Head *g) { - assert(gc_get_refs(g) > 0); + _PyObject_ASSERT_WITH_MSG(FROM_GC(g), + gc_get_refs(g) > 0, + "refcount is too small"); g->_gc_prev -= 1 << _PyGC_PREV_SHIFT; } -/* Get an object's GC head */ -#define AS_GC(o) ((PyGC_Head *)(o)-1) - -/* Get the object given the GC head */ -#define FROM_GC(g) ((PyObject *)(((PyGC_Head *)g)+1)) - /* Python string to use if unhandled exception occurs */ static PyObject *gc_str = NULL; |