diff -r cde3d986da00 Include/traceback.h --- a/Include/traceback.h Mon Mar 14 22:26:53 2016 +0100 +++ b/Include/traceback.h Tue Mar 15 01:34:15 2016 +0100 @@ -66,6 +66,20 @@ PyAPI_DATA(const char*) _Py_DumpTracebac int fd, PyInterpreterState *interp, PyThreadState *current_thread); +#ifndef Py_LIMITED_API + +/* Write an unicode object into the file fd using ascii+backslashreplace. + + This function is signal safe. */ +PyAPI_FUNC(void) _Py_DumpASCII(int fd, PyObject *text); + +/* Format an integer in range [0; 999999] to decimal, + and write it into the file fd. + + This function is signal safe. */ +PyAPI_FUNC(void) _Py_DumpDecimal(int fd, int value); + +#endif /* !Py_LIMITED_API */ #ifdef __cplusplus } diff -r cde3d986da00 Modules/_tracemalloc.c --- a/Modules/_tracemalloc.c Mon Mar 14 22:26:53 2016 +0100 +++ b/Modules/_tracemalloc.c Tue Mar 15 01:34:15 2016 +0100 @@ -1207,6 +1207,62 @@ py_tracemalloc_get_object_traceback(PyOb return traceback_to_pyobject(trace.traceback, NULL); } +static traceback_t* +tracemalloc_get_traceback(const void *ptr) +{ + trace_t trace; + int found; + + if (!tracemalloc_config.tracing) + return NULL; + + found = _Py_HASHTABLE_GET(tracemalloc_traces, ptr, trace); + if (!found) + return NULL; + + return trace.traceback; +} + +#define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str)) + +static void +_PyMem_DumpFrame(int fd, frame_t * frame) +{ + PUTS(fd, " File "); + if (frame->filename != NULL) { + PUTS(fd, "\""); + _Py_DumpASCII(fd, frame->filename); + PUTS(fd, "\""); + } + else { + PUTS(fd, "???"); + } + + /* PyFrame_GetLineNumber() was introduced in Python 2.7.0 and 3.2.0 */ + PUTS(fd, ", line "); + _Py_DumpDecimal(fd, frame->lineno); + PUTS(fd, "\n"); +} + +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 traceback (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" diff -r cde3d986da00 Objects/obmalloc.c --- a/Objects/obmalloc.c Mon Mar 14 22:26:53 2016 +0100 +++ b/Objects/obmalloc.c Tue Mar 15 01:34:15 2016 +0100 @@ -1,5 +1,10 @@ #include "Python.h" + +/* Defined in tracemalloc.c */ +extern void _PyMem_DumpTraceback(int fd, const void *ptr); + + /* Python's malloc wrappers (see pymem.h) */ /* @@ -2202,6 +2207,10 @@ static void } fputc('\n', stderr); } + fputc('\n', stderr); + + fflush(stderr); + _PyMem_DumpTraceback(fileno(stderr), p); } diff -r cde3d986da00 Parser/pgenmain.c --- a/Parser/pgenmain.c Mon Mar 14 22:26:53 2016 +0100 +++ b/Parser/pgenmain.c Tue Mar 15 01:34:15 2016 +0100 @@ -40,9 +40,10 @@ Py_Exit(int sts) #ifdef WITH_THREAD /* Needed by obmalloc.c */ int PyGILState_Check(void) -{ - return 1; -} +{ return 1; } + +void _PyMem_DumpTraceback(int fd, const void *ptr) +{} #endif int diff -r cde3d986da00 Python/traceback.c --- a/Python/traceback.c Mon Mar 14 22:26:53 2016 +0100 +++ b/Python/traceback.c Tue Mar 15 01:34:15 2016 +0100 @@ -493,13 +493,8 @@ reverse_string(char *text, const size_t } } -/* Format an integer in range [0; 999999] to decimal, - and write it into the file fd. - - This function is signal safe. */ - -static void -dump_decimal(int fd, int value) +void +_Py_DumpDecimal(int fd, int value) { char buffer[7]; int len; @@ -535,12 +530,8 @@ dump_hexadecimal(int fd, unsigned long v _Py_write_noraise(fd, buffer, len); } -/* Write an unicode object into the file fd using ascii+backslashreplace. - - This function is signal safe. */ - -static void -dump_ascii(int fd, PyObject *text) +void +_Py_DumpASCII(int fd, PyObject *text) { PyASCIIObject *ascii = (PyASCIIObject *)text; Py_ssize_t i, size; @@ -620,7 +611,7 @@ dump_frame(int fd, PyFrameObject *frame) && PyUnicode_Check(code->co_filename)) { PUTS(fd, "\""); - dump_ascii(fd, code->co_filename); + _Py_DumpASCII(fd, code->co_filename); PUTS(fd, "\""); } else { PUTS(fd, "???"); @@ -629,12 +620,12 @@ dump_frame(int fd, PyFrameObject *frame) /* PyFrame_GetLineNumber() was introduced in Python 2.7.0 and 3.2.0 */ lineno = PyCode_Addr2Line(code, frame->f_lasti); PUTS(fd, ", line "); - dump_decimal(fd, lineno); + _Py_DumpDecimal(fd, lineno); PUTS(fd, " in "); if (code != NULL && code->co_name != NULL && PyUnicode_Check(code->co_name)) - dump_ascii(fd, code->co_name); + _Py_DumpASCII(fd, code->co_name); else PUTS(fd, "???");