summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@redhat.com>2018-10-25 15:31:10 (GMT)
committerGitHub <noreply@github.com>2018-10-25 15:31:10 (GMT)
commit626bff856840f471e98ec627043f780c111a063d (patch)
tree4c8f4da76f3443157e7a06a96d88bbc631650f88 /Modules
parent18618e652c56e61a134e596b315a13c7cb997a89 (diff)
downloadcpython-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.c6
-rw-r--r--Modules/gcmodule.c16
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;