summaryrefslogtreecommitdiffstats
path: root/Modules/_tracemalloc.c
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2016-03-15 21:22:13 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2016-03-15 21:22:13 (GMT)
commit0611c26a58a937dace420691e797fbea21db619b (patch)
tree20f6c60f778a2e999d299b3b015f01d83a10eb4d /Modules/_tracemalloc.c
parentaf584a02a5dee4250e904ff75d22359aee9c2d70 (diff)
downloadcpython-0611c26a58a937dace420691e797fbea21db619b.zip
cpython-0611c26a58a937dace420691e797fbea21db619b.tar.gz
cpython-0611c26a58a937dace420691e797fbea21db619b.tar.bz2
On memory error, dump the memory block traceback
Issue #26564: _PyObject_DebugDumpAddress() now dumps the traceback where a memory block was allocated on memory block. Use the tracemalloc module to get the traceback.
Diffstat (limited to 'Modules/_tracemalloc.c')
-rw-r--r--Modules/_tracemalloc.c67
1 files changed, 56 insertions, 11 deletions
diff --git a/Modules/_tracemalloc.c b/Modules/_tracemalloc.c
index 1940af4..5752904 100644
--- a/Modules/_tracemalloc.c
+++ b/Modules/_tracemalloc.c
@@ -1161,6 +1161,25 @@ finally:
return get_traces.list;
}
+static traceback_t*
+tracemalloc_get_traceback(const void *ptr)
+{
+ trace_t trace;
+ int found;
+
+ if (!tracemalloc_config.tracing)
+ return NULL;
+
+ TABLES_LOCK();
+ found = _Py_HASHTABLE_GET(tracemalloc_traces, ptr, trace);
+ TABLES_UNLOCK();
+
+ if (!found)
+ return NULL;
+
+ return trace.traceback;
+}
+
PyDoc_STRVAR(tracemalloc_get_object_traceback_doc,
"_get_object_traceback(obj)\n"
"\n"
@@ -1175,11 +1194,7 @@ py_tracemalloc_get_object_traceback(PyObject *self, PyObject *obj)
{
PyTypeObject *type;
void *ptr;
- trace_t trace;
- int found;
-
- if (!tracemalloc_config.tracing)
- Py_RETURN_NONE;
+ traceback_t *traceback;
type = Py_TYPE(obj);
if (PyType_IS_GC(type))
@@ -1187,16 +1202,46 @@ py_tracemalloc_get_object_traceback(PyObject *self, PyObject *obj)
else
ptr = (void *)obj;
- TABLES_LOCK();
- found = _Py_HASHTABLE_GET(tracemalloc_traces, ptr, trace);
- TABLES_UNLOCK();
-
- if (!found)
+ traceback = tracemalloc_get_traceback(ptr);
+ if (traceback == NULL)
Py_RETURN_NONE;
- return traceback_to_pyobject(trace.traceback, NULL);
+ return traceback_to_pyobject(traceback, NULL);
+}
+
+#define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str))
+
+static void
+_PyMem_DumpFrame(int fd, frame_t * frame)
+{
+ PUTS(fd, " File \"");
+ _Py_DumpASCII(fd, frame->filename);
+ PUTS(fd, "\", line ");
+ _Py_DumpDecimal(fd, frame->lineno);
+ PUTS(fd, "\n");
}
+/* Dump the traceback where a memory block was allocated into file descriptor
+ fd. The function may block on TABLES_LOCK() but it is unlikely. */
+void
+_PyMem_DumpTraceback(int fd, const void *ptr)
+{
+ traceback_t *traceback;
+ int i;
+
+ traceback = tracemalloc_get_traceback(ptr);
+ if (traceback == NULL)
+ return;
+
+ PUTS(fd, "Memory block allocated at (most recent call first):\n");
+ for (i=0; i < traceback->nframe; i++) {
+ _PyMem_DumpFrame(fd, &traceback->frames[i]);
+ }
+ PUTS(fd, "\n");
+}
+
+#undef PUTS
+
PyDoc_STRVAR(tracemalloc_start_doc,
"start(nframe: int=1)\n"
"\n"