From a5b3af7156594cc0a7964ac808f7807970912c8e Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sun, 13 Oct 2013 21:53:13 +0200 Subject: Issue #18776: atexit callbacks now display their full traceback when they raise an exception. --- Python/pythonrun.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'Python/pythonrun.c') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 9ef653b57a..ee277b67f2 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1880,6 +1880,16 @@ PyErr_Display(PyObject *exception, PyObject *value, PyObject *tb) { PyObject *seen; PyObject *f = PySys_GetObject("stderr"); + if (PyExceptionInstance_Check(value) + && tb != NULL && PyTraceBack_Check(tb)) { + /* Put the traceback on the exception, otherwise it won't get + displayed. See issue #18776. */ + PyObject *cur_tb = PyException_GetTraceback(value); + if (cur_tb == NULL) + PyException_SetTraceback(value, tb); + else + Py_DECREF(cur_tb); + } if (f == Py_None) { /* pass */ } -- cgit v1.2.1 From 54fa1af4e71e74b44edb29fba10bcde115779113 Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Thu, 17 Oct 2013 22:35:35 +1000 Subject: Issue #16129: Add `Py_SetStandardStreamEncoding` This new pre-initialization API allows embedding applications like Blender to force a particular encoding and error handler for the standard IO streams. Also refactors Modules/_testembed.c to let us start testing multiple embedding scenarios. (Initial patch by Bastien Montagne) --- Python/pythonrun.c | 81 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 65 insertions(+), 16 deletions(-) (limited to 'Python/pythonrun.c') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 06f30b0f40..3bcc4742d1 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -134,6 +134,40 @@ Py_IsInitialized(void) return initialized; } +/* Helper to allow an embedding application to override the normal + * mechanism that attempts to figure out an appropriate IO encoding + */ + +static char *_Py_StandardStreamEncoding = NULL; +static char *_Py_StandardStreamErrors = NULL; + +int +Py_SetStandardStreamEncoding(const char *encoding, const char *errors) +{ + if (Py_IsInitialized()) { + /* This is too late to have any effect */ + return -1; + } + if (encoding) { + _Py_StandardStreamEncoding = _PyMem_RawStrdup(encoding); + if (!_Py_StandardStreamEncoding) { + PyErr_NoMemory(); + return -1; + } + } + if (errors) { + _Py_StandardStreamErrors = _PyMem_RawStrdup(errors); + if (!_Py_StandardStreamErrors) { + if (_Py_StandardStreamEncoding) { + PyMem_RawFree(_Py_StandardStreamEncoding); + } + PyErr_NoMemory(); + return -1; + } + } + return 0; +} + /* Global initializations. Can be undone by Py_Finalize(). Don't call this twice without an intervening Py_Finalize() call. When initializations fail, a fatal error is issued and the function does @@ -1088,23 +1122,29 @@ initstdio(void) } Py_DECREF(wrapper); - pythonioencoding = Py_GETENV("PYTHONIOENCODING"); - encoding = errors = NULL; - if (pythonioencoding) { - pythonioencoding = _PyMem_Strdup(pythonioencoding); - if (pythonioencoding == NULL) { - PyErr_NoMemory(); - goto error; - } - errors = strchr(pythonioencoding, ':'); - if (errors) { - *errors = '\0'; - errors++; - if (!*errors) - errors = NULL; + encoding = _Py_StandardStreamEncoding; + errors = _Py_StandardStreamErrors; + if (!encoding || !errors) { + pythonioencoding = Py_GETENV("PYTHONIOENCODING"); + if (pythonioencoding) { + char *err; + pythonioencoding = _PyMem_Strdup(pythonioencoding); + if (pythonioencoding == NULL) { + PyErr_NoMemory(); + goto error; + } + err = strchr(pythonioencoding, ':'); + if (err) { + *err = '\0'; + err++; + if (*err && !errors) { + errors = err; + } + } + if (*pythonioencoding && !encoding) { + encoding = pythonioencoding; + } } - if (*pythonioencoding) - encoding = pythonioencoding; } /* Set sys.stdin */ @@ -1184,6 +1224,15 @@ initstdio(void) status = -1; } + /* We won't need them anymore. */ + if (_Py_StandardStreamEncoding) { + PyMem_RawFree(_Py_StandardStreamEncoding); + _Py_StandardStreamEncoding = NULL; + } + if (_Py_StandardStreamErrors) { + PyMem_RawFree(_Py_StandardStreamErrors); + _Py_StandardStreamErrors = NULL; + } PyMem_Free(pythonioencoding); Py_XDECREF(bimod); Py_XDECREF(iomod); -- cgit v1.2.1 From 595d11f97b0cb5fb5242835f3a4f5db2e4ce08c1 Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Fri, 18 Oct 2013 23:11:47 +1000 Subject: Issue #16129: Py_SetStandardStreamEncoding cleanups - don't call PyErr_NoMemory with interpreter is not initialised - note that it's OK to call _PyMem_RawStrDup here - don't include this in the limited API - capitalise "IO" - be explicit that a non-zero return indicates an error - include versionadded marker in docs --- Python/pythonrun.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'Python/pythonrun.c') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 3bcc4742d1..b963ce1132 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -148,11 +148,17 @@ Py_SetStandardStreamEncoding(const char *encoding, const char *errors) /* This is too late to have any effect */ return -1; } + /* Can't call PyErr_NoMemory() on errors, as Python hasn't been + * initialised yet. + * + * However, the raw memory allocators are initialised appropriately + * as C static variables, so _PyMem_RawStrdup is OK even though + * Py_Initialize hasn't been called yet. + */ if (encoding) { _Py_StandardStreamEncoding = _PyMem_RawStrdup(encoding); if (!_Py_StandardStreamEncoding) { - PyErr_NoMemory(); - return -1; + return -2; } } if (errors) { @@ -161,8 +167,7 @@ Py_SetStandardStreamEncoding(const char *encoding, const char *errors) if (_Py_StandardStreamEncoding) { PyMem_RawFree(_Py_StandardStreamEncoding); } - PyErr_NoMemory(); - return -1; + return -3; } } return 0; -- cgit v1.2.1 From 8717476dc7451dce7e81cacc05650f1d7fbe793c Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Tue, 22 Oct 2013 10:22:29 +0200 Subject: Issue #18603: Ensure that PyOS_mystricmp and PyOS_mystrnicmp are in the Python executable and not removed by the linker's optimizer. --- Python/pythonrun.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Python/pythonrun.c') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index ee277b67f2..832df535f8 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -96,6 +96,10 @@ int Py_HashRandomizationFlag = 0; /* for -R and PYTHONHASHSEED */ PyThreadState *_Py_Finalizing = NULL; +/* Hack to force loading of object files */ +int (*_PyOS_mystrnicmp_hack)(const char *, const char *, Py_ssize_t) = \ + PyOS_mystrnicmp; /* Python/pystrcmp.o */ + /* PyModule_GetWarningsModule is no longer necessary as of 2.6 since _warnings is builtin. This API should not be used. */ PyObject * -- cgit v1.2.1 From 43d34bd80f869e7121089a0e4d3b4b1e58453bb8 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 6 Nov 2013 18:28:21 +0100 Subject: Issue #19512: _print_total_refs() now uses an identifier to get "showrefcount" key from sys._xoptions --- Python/pythonrun.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'Python/pythonrun.c') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 15a48f9947..dcd3664d14 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -38,15 +38,13 @@ #ifdef Py_REF_DEBUG static void _print_total_refs(void) { - PyObject *xoptions, *key, *value; + PyObject *xoptions, *value; + _Py_IDENTIFIER(showrefcount); + xoptions = PySys_GetXOptions(); if (xoptions == NULL) return; - key = PyUnicode_FromString("showrefcount"); - if (key == NULL) - return; - value = PyDict_GetItem(xoptions, key); - Py_DECREF(key); + value = _PyDict_GetItemId(xoptions, &PyId_showrefcount); if (value == Py_True) fprintf(stderr, "[%" PY_FORMAT_SIZE_T "d refs, " -- cgit v1.2.1 From 66cb4b750939e85ca23732e63996f27135b7c334 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 6 Nov 2013 18:41:07 +0100 Subject: Issue #19512: Add PyRun_InteractiveOneObject() function Only decode the filename once. PyRun_InteractiveOneObject() uses an identifier for "" string, so the byte string is only decoded once. --- Python/pythonrun.c | 111 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 82 insertions(+), 29 deletions(-) (limited to 'Python/pythonrun.c') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index dcd3664d14..61d03521e8 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -73,7 +73,7 @@ static int initfsencoding(PyInterpreterState *interp); static void initsite(void); static int initstdio(void); static void flush_io(void); -static PyObject *run_mod(mod_ty, const char *, PyObject *, PyObject *, +static PyObject *run_mod(mod_ty, PyObject *, PyObject *, PyObject *, PyCompilerFlags *, PyArena *); static PyObject *run_pyc_file(FILE *, const char *, PyObject *, PyObject *, PyCompilerFlags *); @@ -1265,12 +1265,18 @@ PyRun_AnyFileExFlags(FILE *fp, const char *filename, int closeit, } int -PyRun_InteractiveLoopFlags(FILE *fp, const char *filename, PyCompilerFlags *flags) +PyRun_InteractiveLoopFlags(FILE *fp, const char *filename_str, PyCompilerFlags *flags) { - PyObject *v; - int ret; + PyObject *filename, *v; + int ret, err; PyCompilerFlags local_flags; + filename = PyUnicode_DecodeFSDefault(filename_str); + if (filename == NULL) { + PyErr_Print(); + return -1; + } + if (flags == NULL) { flags = &local_flags; local_flags.cf_flags = 0; @@ -1285,16 +1291,21 @@ PyRun_InteractiveLoopFlags(FILE *fp, const char *filename, PyCompilerFlags *flag PySys_SetObject("ps2", v = PyUnicode_FromString("... ")); Py_XDECREF(v); } + err = -1; for (;;) { - ret = PyRun_InteractiveOneFlags(fp, filename, flags); + ret = PyRun_InteractiveOneObject(fp, filename, flags); PRINT_TOTAL_REFS(); - if (ret == E_EOF) - return 0; + if (ret == E_EOF) { + err = 0; + break; + } /* if (ret == E_NOMEM) - return -1; + break; */ } + Py_DECREF(filename); + return err; } /* compute parser flags based on compiler flags */ @@ -1322,14 +1333,21 @@ static int PARSER_FLAGS(PyCompilerFlags *flags) #endif int -PyRun_InteractiveOneFlags(FILE *fp, const char *filename, PyCompilerFlags *flags) +PyRun_InteractiveOneObject(FILE *fp, PyObject *filename, PyCompilerFlags *flags) { - PyObject *m, *d, *v, *w, *oenc = NULL; + PyObject *m, *d, *v, *w, *oenc = NULL, *mod_name; mod_ty mod; PyArena *arena; char *ps1 = "", *ps2 = "", *enc = NULL; int errcode = 0; _Py_IDENTIFIER(encoding); + _Py_IDENTIFIER(__main__); + + mod_name = _PyUnicode_FromId(&PyId___main__); /* borrowed */ + if (mod_name == NULL) { + PyErr_Print(); + return -1; + } if (fp == stdin) { /* Fetch encoding from sys.stdin if possible. */ @@ -1375,9 +1393,9 @@ PyRun_InteractiveOneFlags(FILE *fp, const char *filename, PyCompilerFlags *flags Py_XDECREF(oenc); return -1; } - mod = PyParser_ASTFromFile(fp, filename, enc, - Py_single_input, ps1, ps2, - flags, &errcode, arena); + mod = PyParser_ASTFromFileObject(fp, filename, enc, + Py_single_input, ps1, ps2, + flags, &errcode, arena); Py_XDECREF(v); Py_XDECREF(w); Py_XDECREF(oenc); @@ -1390,7 +1408,7 @@ PyRun_InteractiveOneFlags(FILE *fp, const char *filename, PyCompilerFlags *flags PyErr_Print(); return -1; } - m = PyImport_AddModule("__main__"); + m = PyImport_AddModuleObject(mod_name); if (m == NULL) { PyArena_Free(arena); return -1; @@ -1407,6 +1425,23 @@ PyRun_InteractiveOneFlags(FILE *fp, const char *filename, PyCompilerFlags *flags return 0; } +int +PyRun_InteractiveOneFlags(FILE *fp, const char *filename_str, PyCompilerFlags *flags) +{ + PyObject *filename; + int res; + + filename = PyUnicode_DecodeFSDefault(filename_str); + if (filename == NULL) { + PyErr_Print(); + return -1; + } + res = PyRun_InteractiveOneObject(fp, filename, flags); + Py_DECREF(filename); + return res; +} + + /* Check whether a file maybe a pyc file: Look at the extension, the file type, and, if we may close it, at the first few bytes. */ @@ -2010,37 +2045,55 @@ PyRun_StringFlags(const char *str, int start, PyObject *globals, { PyObject *ret = NULL; mod_ty mod; - PyArena *arena = PyArena_New(); + PyArena *arena; + _Py_static_string(PyId_string, ""); + PyObject *filename; + + filename = _PyUnicode_FromId(&PyId_string); /* borrowed */ + if (filename == NULL) + return NULL; + + arena = PyArena_New(); if (arena == NULL) return NULL; - mod = PyParser_ASTFromString(str, "", start, flags, arena); + mod = PyParser_ASTFromStringObject(str, filename, start, flags, arena); if (mod != NULL) - ret = run_mod(mod, "", globals, locals, flags, arena); + ret = run_mod(mod, filename, globals, locals, flags, arena); PyArena_Free(arena); return ret; } PyObject * -PyRun_FileExFlags(FILE *fp, const char *filename, int start, PyObject *globals, +PyRun_FileExFlags(FILE *fp, const char *filename_str, int start, PyObject *globals, PyObject *locals, int closeit, PyCompilerFlags *flags) { - PyObject *ret; + PyObject *ret = NULL; mod_ty mod; - PyArena *arena = PyArena_New(); + PyArena *arena = NULL; + PyObject *filename; + + filename = PyUnicode_DecodeFSDefault(filename_str); + if (filename == NULL) + goto exit; + + arena = PyArena_New(); if (arena == NULL) - return NULL; + goto exit; - mod = PyParser_ASTFromFile(fp, filename, NULL, start, 0, 0, - flags, NULL, arena); + mod = PyParser_ASTFromFileObject(fp, filename, NULL, start, 0, 0, + flags, NULL, arena); if (closeit) fclose(fp); if (mod == NULL) { - PyArena_Free(arena); - return NULL; + goto exit; } ret = run_mod(mod, filename, globals, locals, flags, arena); - PyArena_Free(arena); + +exit: + Py_XDECREF(filename); + if (arena != NULL) + PyArena_Free(arena); return ret; } @@ -2075,12 +2128,12 @@ flush_io(void) } static PyObject * -run_mod(mod_ty mod, const char *filename, PyObject *globals, PyObject *locals, - PyCompilerFlags *flags, PyArena *arena) +run_mod(mod_ty mod, PyObject *filename, PyObject *globals, PyObject *locals, + PyCompilerFlags *flags, PyArena *arena) { PyCodeObject *co; PyObject *v; - co = PyAST_Compile(mod, filename, flags, arena); + co = PyAST_CompileObject(mod, filename, flags, -1, arena); if (co == NULL) return NULL; v = PyEval_EvalCode((PyObject*)co, globals, locals); -- cgit v1.2.1 From abe98ac333cb6792ed82b144822738e50e38d443 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 6 Nov 2013 22:41:44 +0100 Subject: Issue #19512: add some common identifiers to only create common strings once, instead of creating temporary Unicode string objects Add also more identifiers in pythonrun.c to avoid temporary Unicode string objets for the interactive interpreter. --- Python/pythonrun.c | 59 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 22 deletions(-) (limited to 'Python/pythonrun.c') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 61d03521e8..e510e6f78a 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -35,6 +35,21 @@ #define PATH_MAX MAXPATHLEN #endif +/* Common identifiers */ +_Py_Identifier _PyId_argv = _Py_static_string_init("argv"); +_Py_Identifier _PyId_path = _Py_static_string_init("path"); +_Py_Identifier _PyId_stdin = _Py_static_string_init("stdin"); +_Py_Identifier _PyId_stdout = _Py_static_string_init("stdout"); +_Py_Identifier _PyId_stderr = _Py_static_string_init("stderr"); + +/* local identifiers */ +_Py_IDENTIFIER(excepthook); +_Py_IDENTIFIER(ps1); +_Py_IDENTIFIER(ps2); +_Py_IDENTIFIER(last_type); +_Py_IDENTIFIER(last_value); +_Py_IDENTIFIER(last_traceback); + #ifdef Py_REF_DEBUG static void _print_total_refs(void) { @@ -412,7 +427,7 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib) pstderr = PyFile_NewStdPrinter(fileno(stderr)); if (pstderr == NULL) Py_FatalError("Py_Initialize: can't set preliminary stderr"); - PySys_SetObject("stderr", pstderr); + _PySys_SetObjectId(&_PyId_stderr, pstderr); PySys_SetObject("__stderr__", pstderr); Py_DECREF(pstderr); @@ -497,8 +512,8 @@ file_is_closed(PyObject *fobj) static void flush_std_files(void) { - PyObject *fout = PySys_GetObject("stdout"); - PyObject *ferr = PySys_GetObject("stderr"); + PyObject *fout = _PySys_GetObjectId(&_PyId_stdout); + PyObject *ferr = _PySys_GetObjectId(&_PyId_stderr); PyObject *tmp; _Py_IDENTIFIER(flush); @@ -776,7 +791,7 @@ Py_NewInterpreter(void) pstderr = PyFile_NewStdPrinter(fileno(stderr)); if (pstderr == NULL) Py_FatalError("Py_Initialize: can't set preliminary stderr"); - PySys_SetObject("stderr", pstderr); + _PySys_SetObjectId(&_PyId_stderr, pstderr); PySys_SetObject("__stderr__", pstderr); Py_DECREF(pstderr); @@ -1170,7 +1185,7 @@ initstdio(void) goto error; } /* if (fd < 0) */ PySys_SetObject("__stdin__", std); - PySys_SetObject("stdin", std); + _PySys_SetObjectId(&_PyId_stdin, std); Py_DECREF(std); /* Set sys.stdout */ @@ -1185,7 +1200,7 @@ initstdio(void) goto error; } /* if (fd < 0) */ PySys_SetObject("__stdout__", std); - PySys_SetObject("stdout", std); + _PySys_SetObjectId(&_PyId_stdout, std); Py_DECREF(std); #if 1 /* Disable this if you have trouble debugging bootstrap stuff */ @@ -1219,7 +1234,7 @@ initstdio(void) Py_DECREF(std); goto error; } - if (PySys_SetObject("stderr", std) < 0) { + if (_PySys_SetObjectId(&_PyId_stderr, std) < 0) { Py_DECREF(std); goto error; } @@ -1281,14 +1296,14 @@ PyRun_InteractiveLoopFlags(FILE *fp, const char *filename_str, PyCompilerFlags * flags = &local_flags; local_flags.cf_flags = 0; } - v = PySys_GetObject("ps1"); + v = _PySys_GetObjectId(&PyId_ps1); if (v == NULL) { - PySys_SetObject("ps1", v = PyUnicode_FromString(">>> ")); + _PySys_SetObjectId(&PyId_ps1, v = PyUnicode_FromString(">>> ")); Py_XDECREF(v); } - v = PySys_GetObject("ps2"); + v = _PySys_GetObjectId(&PyId_ps2); if (v == NULL) { - PySys_SetObject("ps2", v = PyUnicode_FromString("... ")); + _PySys_SetObjectId(&PyId_ps2, v = PyUnicode_FromString("... ")); Py_XDECREF(v); } err = -1; @@ -1351,7 +1366,7 @@ PyRun_InteractiveOneObject(FILE *fp, PyObject *filename, PyCompilerFlags *flags) if (fp == stdin) { /* Fetch encoding from sys.stdin if possible. */ - v = PySys_GetObject("stdin"); + v = _PySys_GetObjectId(&_PyId_stdin); if (v && v != Py_None) { oenc = _PyObject_GetAttrId(v, &PyId_encoding); if (oenc) @@ -1360,7 +1375,7 @@ PyRun_InteractiveOneObject(FILE *fp, PyObject *filename, PyCompilerFlags *flags) PyErr_Clear(); } } - v = PySys_GetObject("ps1"); + v = _PySys_GetObjectId(&PyId_ps1); if (v != NULL) { v = PyObject_Str(v); if (v == NULL) @@ -1373,7 +1388,7 @@ PyRun_InteractiveOneObject(FILE *fp, PyObject *filename, PyCompilerFlags *flags) } } } - w = PySys_GetObject("ps2"); + w = _PySys_GetObjectId(&PyId_ps2); if (w != NULL) { w = PyObject_Str(w); if (w == NULL) @@ -1752,7 +1767,7 @@ handle_system_exit(void) if (PyLong_Check(value)) exitcode = (int)PyLong_AsLong(value); else { - PyObject *sys_stderr = PySys_GetObject("stderr"); + PyObject *sys_stderr = _PySys_GetObjectId(&_PyId_stderr); if (sys_stderr != NULL && sys_stderr != Py_None) { PyFile_WriteObject(value, sys_stderr, Py_PRINT_RAW); } else { @@ -1795,11 +1810,11 @@ PyErr_PrintEx(int set_sys_last_vars) return; /* Now we know v != NULL too */ if (set_sys_last_vars) { - PySys_SetObject("last_type", exception); - PySys_SetObject("last_value", v); - PySys_SetObject("last_traceback", tb); + _PySys_SetObjectId(&PyId_last_type, exception); + _PySys_SetObjectId(&PyId_last_value, v); + _PySys_SetObjectId(&PyId_last_traceback, tb); } - hook = PySys_GetObject("excepthook"); + hook = _PySys_GetObjectId(&PyId_excepthook); if (hook) { PyObject *args = PyTuple_Pack(3, exception, v, tb); PyObject *result = PyEval_CallObject(hook, args); @@ -2009,7 +2024,7 @@ void PyErr_Display(PyObject *exception, PyObject *value, PyObject *tb) { PyObject *seen; - PyObject *f = PySys_GetObject("stderr"); + PyObject *f = _PySys_GetObjectId(&_PyId_stderr); if (PyExceptionInstance_Check(value) && tb != NULL && PyTraceBack_Check(tb)) { /* Put the traceback on the exception, otherwise it won't get @@ -2107,7 +2122,7 @@ flush_io(void) /* Save the current exception */ PyErr_Fetch(&type, &value, &traceback); - f = PySys_GetObject("stderr"); + f = _PySys_GetObjectId(&_PyId_stderr); if (f != NULL) { r = _PyObject_CallMethodId(f, &PyId_flush, ""); if (r) @@ -2115,7 +2130,7 @@ flush_io(void) else PyErr_Clear(); } - f = PySys_GetObject("stdout"); + f = _PySys_GetObjectId(&_PyId_stdout); if (f != NULL) { r = _PyObject_CallMethodId(f, &PyId_flush, ""); if (r) -- cgit v1.2.1 From 05bfe3160e622f7d33904a12c89fe0a155222fff Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 7 Nov 2013 00:12:30 +0100 Subject: print_exception(): don't encode the module name to UTF-8 Replace _PyUnicode_AsString()+strcmp() with PyUnicode_CompareWithASCIIString(). --- Python/pythonrun.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'Python/pythonrun.c') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index e510e6f78a..e0c863811a 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1928,10 +1928,9 @@ print_exception(PyObject *f, PyObject *value) err = PyFile_WriteString("", f); } else { - char* modstr = _PyUnicode_AsString(moduleName); - if (modstr && strcmp(modstr, "builtins")) + if (PyUnicode_CompareWithASCIIString(moduleName, "builtins") != 0) { - err = PyFile_WriteString(modstr, f); + err = PyFile_WriteObject(moduleName, f, Py_PRINT_RAW); err += PyFile_WriteString(".", f); } Py_DECREF(moduleName); -- cgit v1.2.1 From 36fcb30e4fb853c47112a363d46b9e77f3c5e97d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 7 Nov 2013 00:46:04 +0100 Subject: Issue #19512: add _PyUnicode_CompareWithId() function _PyUnicode_CompareWithId() is faster than PyUnicode_CompareWithASCIIString() when both strings are equal and interned. Add also _PyId_builtins identifier for "builtins" common string. --- Python/pythonrun.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Python/pythonrun.c') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index e0c863811a..be41de67f2 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -37,6 +37,7 @@ /* Common identifiers */ _Py_Identifier _PyId_argv = _Py_static_string_init("argv"); +_Py_Identifier _PyId_builtins = _Py_static_string_init("builtins"); _Py_Identifier _PyId_path = _Py_static_string_init("path"); _Py_Identifier _PyId_stdin = _Py_static_string_init("stdin"); _Py_Identifier _PyId_stdout = _Py_static_string_init("stdout"); @@ -1928,7 +1929,7 @@ print_exception(PyObject *f, PyObject *value) err = PyFile_WriteString("", f); } else { - if (PyUnicode_CompareWithASCIIString(moduleName, "builtins") != 0) + if (_PyUnicode_CompareWithId(moduleName, &_PyId_builtins) != 0) { err = PyFile_WriteObject(moduleName, f, Py_PRINT_RAW); err += PyFile_WriteString(".", f); -- cgit v1.2.1 From f8a141c2766dbd2eadcb245e207f4242295710c8 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 7 Nov 2013 12:37:56 +0100 Subject: print_error_text() doesn't encode the filename anymore Use aslo PyUnicode_FromFormat() to format the line so only one call to PyFile_WriteObject() is needed. tb_displayline() of Python/traceback.c has similar implementation. --- Python/pythonrun.c | 62 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 27 deletions(-) (limited to 'Python/pythonrun.c') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index be41de67f2..5115c5724c 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -50,6 +50,7 @@ _Py_IDENTIFIER(ps2); _Py_IDENTIFIER(last_type); _Py_IDENTIFIER(last_value); _Py_IDENTIFIER(last_traceback); +_Py_static_string(PyId_string, ""); #ifdef Py_REF_DEBUG static @@ -1625,8 +1626,8 @@ PyRun_SimpleStringFlags(const char *command, PyCompilerFlags *flags) } static int -parse_syntax_error(PyObject *err, PyObject **message, const char **filename, - int *lineno, int *offset, const char **text) +parse_syntax_error(PyObject *err, PyObject **message, PyObject **filename, + int *lineno, int *offset, PyObject **text) { long hold; PyObject *v; @@ -1637,6 +1638,7 @@ parse_syntax_error(PyObject *err, PyObject **message, const char **filename, _Py_IDENTIFIER(text); *message = NULL; + *filename = NULL; /* new style errors. `err' is an instance */ *message = _PyObject_GetAttrId(err, &PyId_msg); @@ -1648,13 +1650,13 @@ parse_syntax_error(PyObject *err, PyObject **message, const char **filename, goto finally; if (v == Py_None) { Py_DECREF(v); - *filename = NULL; + *filename = _PyUnicode_FromId(&PyId_string); + if (*filename == NULL) + goto finally; + Py_INCREF(*filename); } else { - *filename = _PyUnicode_AsString(v); - Py_DECREF(v); - if (!*filename) - goto finally; + *filename = v; } v = _PyObject_GetAttrId(err, &PyId_lineno); @@ -1688,15 +1690,13 @@ parse_syntax_error(PyObject *err, PyObject **message, const char **filename, *text = NULL; } else { - *text = _PyUnicode_AsString(v); - Py_DECREF(v); - if (!*text) - goto finally; + *text = v; } return 1; finally: Py_XDECREF(*message); + Py_XDECREF(*filename); return 0; } @@ -1707,9 +1707,15 @@ PyErr_Print(void) } static void -print_error_text(PyObject *f, int offset, const char *text) +print_error_text(PyObject *f, int offset, PyObject *text_obj) { + char *text; char *nl; + + text = _PyUnicode_AsString(text_obj); + if (text == NULL) + return; + if (offset >= 0) { if (offset > 0 && offset == strlen(text) && text[offset - 1] == '\n') offset--; @@ -1880,27 +1886,30 @@ print_exception(PyObject *f, PyObject *value) if (err == 0 && _PyObject_HasAttrId(value, &PyId_print_file_and_line)) { - PyObject *message; - const char *filename, *text; + PyObject *message, *filename, *text; int lineno, offset; if (!parse_syntax_error(value, &message, &filename, &lineno, &offset, &text)) PyErr_Clear(); else { - char buf[10]; - PyFile_WriteString(" File \"", f); - if (filename == NULL) - PyFile_WriteString("", f); - else - PyFile_WriteString(filename, f); - PyFile_WriteString("\", line ", f); - PyOS_snprintf(buf, sizeof(buf), "%d", lineno); - PyFile_WriteString(buf, f); - PyFile_WriteString("\n", f); - if (text != NULL) - print_error_text(f, offset, text); + PyObject *line; + Py_DECREF(value); value = message; + + line = PyUnicode_FromFormat(" File \"%U\", line %d\n", + filename, lineno); + Py_DECREF(filename); + if (line != NULL) { + PyFile_WriteObject(line, f, Py_PRINT_RAW); + Py_DECREF(line); + } + + if (text != NULL) { + print_error_text(f, offset, text); + Py_DECREF(text); + } + /* Can't be bothered to check all those PyFile_WriteString() calls */ if (PyErr_Occurred()) @@ -2061,7 +2070,6 @@ PyRun_StringFlags(const char *str, int start, PyObject *globals, PyObject *ret = NULL; mod_ty mod; PyArena *arena; - _Py_static_string(PyId_string, ""); PyObject *filename; filename = _PyUnicode_FromId(&PyId_string); /* borrowed */ -- cgit v1.2.1 From 359ed22ea49d63923b451351ebf80decaaa7b79e Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 7 Nov 2013 23:07:29 +0100 Subject: Issue #19512, #19515: remove shared identifiers, move identifiers where they are used. Move also _Py_IDENTIFIER() defintions to the top in modified files to remove identifiers duplicated in the same file. --- Python/pythonrun.c | 45 ++++++++++++++++++++------------------------- 1 file changed, 20 insertions(+), 25 deletions(-) (limited to 'Python/pythonrun.c') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 5115c5724c..922446ecf6 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -35,21 +35,16 @@ #define PATH_MAX MAXPATHLEN #endif -/* Common identifiers */ -_Py_Identifier _PyId_argv = _Py_static_string_init("argv"); -_Py_Identifier _PyId_builtins = _Py_static_string_init("builtins"); -_Py_Identifier _PyId_path = _Py_static_string_init("path"); -_Py_Identifier _PyId_stdin = _Py_static_string_init("stdin"); -_Py_Identifier _PyId_stdout = _Py_static_string_init("stdout"); -_Py_Identifier _PyId_stderr = _Py_static_string_init("stderr"); - -/* local identifiers */ +_Py_IDENTIFIER(builtins); _Py_IDENTIFIER(excepthook); -_Py_IDENTIFIER(ps1); -_Py_IDENTIFIER(ps2); +_Py_IDENTIFIER(last_traceback); _Py_IDENTIFIER(last_type); _Py_IDENTIFIER(last_value); -_Py_IDENTIFIER(last_traceback); +_Py_IDENTIFIER(ps1); +_Py_IDENTIFIER(ps2); +_Py_IDENTIFIER(stdin); +_Py_IDENTIFIER(stdout); +_Py_IDENTIFIER(stderr); _Py_static_string(PyId_string, ""); #ifdef Py_REF_DEBUG @@ -429,7 +424,7 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib) pstderr = PyFile_NewStdPrinter(fileno(stderr)); if (pstderr == NULL) Py_FatalError("Py_Initialize: can't set preliminary stderr"); - _PySys_SetObjectId(&_PyId_stderr, pstderr); + _PySys_SetObjectId(&PyId_stderr, pstderr); PySys_SetObject("__stderr__", pstderr); Py_DECREF(pstderr); @@ -514,8 +509,8 @@ file_is_closed(PyObject *fobj) static void flush_std_files(void) { - PyObject *fout = _PySys_GetObjectId(&_PyId_stdout); - PyObject *ferr = _PySys_GetObjectId(&_PyId_stderr); + PyObject *fout = _PySys_GetObjectId(&PyId_stdout); + PyObject *ferr = _PySys_GetObjectId(&PyId_stderr); PyObject *tmp; _Py_IDENTIFIER(flush); @@ -793,7 +788,7 @@ Py_NewInterpreter(void) pstderr = PyFile_NewStdPrinter(fileno(stderr)); if (pstderr == NULL) Py_FatalError("Py_Initialize: can't set preliminary stderr"); - _PySys_SetObjectId(&_PyId_stderr, pstderr); + _PySys_SetObjectId(&PyId_stderr, pstderr); PySys_SetObject("__stderr__", pstderr); Py_DECREF(pstderr); @@ -1187,7 +1182,7 @@ initstdio(void) goto error; } /* if (fd < 0) */ PySys_SetObject("__stdin__", std); - _PySys_SetObjectId(&_PyId_stdin, std); + _PySys_SetObjectId(&PyId_stdin, std); Py_DECREF(std); /* Set sys.stdout */ @@ -1202,7 +1197,7 @@ initstdio(void) goto error; } /* if (fd < 0) */ PySys_SetObject("__stdout__", std); - _PySys_SetObjectId(&_PyId_stdout, std); + _PySys_SetObjectId(&PyId_stdout, std); Py_DECREF(std); #if 1 /* Disable this if you have trouble debugging bootstrap stuff */ @@ -1236,7 +1231,7 @@ initstdio(void) Py_DECREF(std); goto error; } - if (_PySys_SetObjectId(&_PyId_stderr, std) < 0) { + if (_PySys_SetObjectId(&PyId_stderr, std) < 0) { Py_DECREF(std); goto error; } @@ -1368,7 +1363,7 @@ PyRun_InteractiveOneObject(FILE *fp, PyObject *filename, PyCompilerFlags *flags) if (fp == stdin) { /* Fetch encoding from sys.stdin if possible. */ - v = _PySys_GetObjectId(&_PyId_stdin); + v = _PySys_GetObjectId(&PyId_stdin); if (v && v != Py_None) { oenc = _PyObject_GetAttrId(v, &PyId_encoding); if (oenc) @@ -1774,7 +1769,7 @@ handle_system_exit(void) if (PyLong_Check(value)) exitcode = (int)PyLong_AsLong(value); else { - PyObject *sys_stderr = _PySys_GetObjectId(&_PyId_stderr); + PyObject *sys_stderr = _PySys_GetObjectId(&PyId_stderr); if (sys_stderr != NULL && sys_stderr != Py_None) { PyFile_WriteObject(value, sys_stderr, Py_PRINT_RAW); } else { @@ -1938,7 +1933,7 @@ print_exception(PyObject *f, PyObject *value) err = PyFile_WriteString("", f); } else { - if (_PyUnicode_CompareWithId(moduleName, &_PyId_builtins) != 0) + if (_PyUnicode_CompareWithId(moduleName, &PyId_builtins) != 0) { err = PyFile_WriteObject(moduleName, f, Py_PRINT_RAW); err += PyFile_WriteString(".", f); @@ -2033,7 +2028,7 @@ void PyErr_Display(PyObject *exception, PyObject *value, PyObject *tb) { PyObject *seen; - PyObject *f = _PySys_GetObjectId(&_PyId_stderr); + PyObject *f = _PySys_GetObjectId(&PyId_stderr); if (PyExceptionInstance_Check(value) && tb != NULL && PyTraceBack_Check(tb)) { /* Put the traceback on the exception, otherwise it won't get @@ -2130,7 +2125,7 @@ flush_io(void) /* Save the current exception */ PyErr_Fetch(&type, &value, &traceback); - f = _PySys_GetObjectId(&_PyId_stderr); + f = _PySys_GetObjectId(&PyId_stderr); if (f != NULL) { r = _PyObject_CallMethodId(f, &PyId_flush, ""); if (r) @@ -2138,7 +2133,7 @@ flush_io(void) else PyErr_Clear(); } - f = _PySys_GetObjectId(&_PyId_stdout); + f = _PySys_GetObjectId(&PyId_stdout); if (f != NULL) { r = _PyObject_CallMethodId(f, &PyId_flush, ""); if (r) -- cgit v1.2.1 From 355e6272737a813c3db93acf944cc25a5c93aaa1 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 12 Nov 2013 16:37:55 +0100 Subject: Close #19466: Clear the frames of daemon threads earlier during the Python shutdown to call objects destructors. So "unclosed file" resource warnings are now corretly emitted for daemon threads. --- Python/pythonrun.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'Python/pythonrun.c') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 922446ecf6..78942880e4 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -576,11 +576,13 @@ Py_Finalize(void) _Py_Finalizing = tstate; initialized = 0; - /* Flush stdout+stderr */ - flush_std_files(); - - /* Disable signal handling */ - PyOS_FiniInterrupts(); + /* Destroy the state of all threads except of the current thread: in + practice, only daemon threads should still be alive. Clear frames of + other threads to call objects destructor. Destructors will be called in + the current Python thread. Since _Py_Finalizing has been set, no other + Python threads can lock the GIL at this point (if they try, they will + exit immediatly). */ + _PyThreadState_DeleteExcept(tstate); /* Collect garbage. This may call finalizers; it's nice to call these * before all modules are destroyed. @@ -595,6 +597,7 @@ Py_Finalize(void) * XXX I haven't seen a real-life report of either of these. */ PyGC_Collect(); + #ifdef COUNT_ALLOCS /* With COUNT_ALLOCS, it helps to run GC multiple times: each collection might release some types from the type @@ -602,6 +605,13 @@ Py_Finalize(void) while (PyGC_Collect() > 0) /* nothing */; #endif + + /* Flush stdout+stderr */ + flush_std_files(); + + /* Disable signal handling */ + PyOS_FiniInterrupts(); + /* Destroy all modules */ PyImport_Cleanup(); -- cgit v1.2.1 From 24d2bc62d4f65e830305258cd3b4e8b31e4f4634 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 12 Nov 2013 17:18:51 +0100 Subject: Issue #19466: Fix typo. Patch written by Vajrasky Kok. --- Python/pythonrun.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python/pythonrun.c') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 78942880e4..8a59169d4f 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -581,7 +581,7 @@ Py_Finalize(void) other threads to call objects destructor. Destructors will be called in the current Python thread. Since _Py_Finalizing has been set, no other Python threads can lock the GIL at this point (if they try, they will - exit immediatly). */ + exit immediately). */ _PyThreadState_DeleteExcept(tstate); /* Collect garbage. This may call finalizers; it's nice to call these -- cgit v1.2.1 From fb9987791e8c7266ae19cf54761130808e66538b Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 12 Nov 2013 21:39:02 +0100 Subject: Issue #19515: Remove identifiers duplicated in the same file. Patch written by Andrei Dorian Duma. --- Python/pythonrun.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'Python/pythonrun.c') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 8a59169d4f..8ccf70dea9 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -37,9 +37,11 @@ _Py_IDENTIFIER(builtins); _Py_IDENTIFIER(excepthook); +_Py_IDENTIFIER(flush); _Py_IDENTIFIER(last_traceback); _Py_IDENTIFIER(last_type); _Py_IDENTIFIER(last_value); +_Py_IDENTIFIER(name); _Py_IDENTIFIER(ps1); _Py_IDENTIFIER(ps2); _Py_IDENTIFIER(stdin); @@ -215,7 +217,6 @@ get_codec_name(const char *encoding) { char *name_utf8, *name_str; PyObject *codec, *name = NULL; - _Py_IDENTIFIER(name); codec = _PyCodec_Lookup(encoding); if (!codec) @@ -512,7 +513,6 @@ flush_std_files(void) PyObject *fout = _PySys_GetObjectId(&PyId_stdout); PyObject *ferr = _PySys_GetObjectId(&PyId_stderr); PyObject *tmp; - _Py_IDENTIFIER(flush); if (fout != NULL && fout != Py_None && !file_is_closed(fout)) { tmp = _PyObject_CallMethodId(fout, &PyId_flush, ""); @@ -1009,7 +1009,6 @@ create_stdio(PyObject* io, _Py_IDENTIFIER(open); _Py_IDENTIFIER(isatty); _Py_IDENTIFIER(TextIOWrapper); - _Py_IDENTIFIER(name); _Py_IDENTIFIER(mode); /* stdin is always opened in buffered mode, first because it shouldn't @@ -2130,7 +2129,6 @@ flush_io(void) { PyObject *f, *r; PyObject *type, *value, *traceback; - _Py_IDENTIFIER(flush); /* Save the current exception */ PyErr_Fetch(&type, &value, &traceback); -- cgit v1.2.1 From c863d54fbba4643a3c4c8d7244222f4131389993 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 15 Nov 2013 17:09:24 +0100 Subject: pythonrun.c: fix Py_GetPythonHome(), use Py_ARRAY_LENGTH() to get the size of the env_home buffer, not PATH_MAX+1. env_home is declared using MAXPATHLEN+1, and PATH_MAX is not declared on IRIX. --- Python/pythonrun.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'Python/pythonrun.c') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 832df535f8..e02dbe2be1 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -817,8 +817,9 @@ Py_GetPythonHome(void) if (home == NULL && !Py_IgnoreEnvironmentFlag) { char* chome = Py_GETENV("PYTHONHOME"); if (chome) { - size_t r = mbstowcs(env_home, chome, PATH_MAX+1); - if (r != (size_t)-1 && r <= PATH_MAX) + size_t size = Py_ARRAY_LENGTH(env_home); + size_t r = mbstowcs(env_home, chome, size); + if (r != (size_t)-1 && r < size) home = env_home; } -- cgit v1.2.1 From 1f4288b872047826fa7bc66ab5fe785e61a095b1 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Wed, 20 Nov 2013 11:46:18 +0100 Subject: ssue #19183: Implement PEP 456 'secure and interchangeable hash algorithm'. Python now uses SipHash24 on all major platforms. --- Python/pythonrun.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'Python/pythonrun.c') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index e427be3174..b5d57dfcbf 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -104,6 +104,7 @@ extern int _PyLong_Init(void); extern void PyLong_Fini(void); extern int _PyFaulthandler_Init(void); extern void _PyFaulthandler_Fini(void); +extern void _PyHash_Fini(void); #ifdef WITH_THREAD extern void _PyGILState_Init(PyInterpreterState *, PyThreadState *); @@ -650,6 +651,8 @@ Py_Finalize(void) #ifdef COUNT_ALLOCS dump_counts(stdout); #endif + /* dump hash stats */ + _PyHash_Fini(); PRINT_TOTAL_REFS(); -- cgit v1.2.1 From ccdf7c7327a9087370fd0b419eff377807a1070b Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 23 Nov 2013 12:27:24 +0100 Subject: Issue #18874: Implement the PEP 454 (tracemalloc) --- Python/pythonrun.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Python/pythonrun.c') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index b5d57dfcbf..3adbbd7373 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -105,6 +105,7 @@ extern void PyLong_Fini(void); extern int _PyFaulthandler_Init(void); extern void _PyFaulthandler_Fini(void); extern void _PyHash_Fini(void); +extern int _PyTraceMalloc_Init(void); #ifdef WITH_THREAD extern void _PyGILState_Init(PyInterpreterState *, PyThreadState *); @@ -454,6 +455,9 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib) if (install_sigs) initsigs(); /* Signal handling stuff, including initintr() */ + if (_PyTraceMalloc_Init() < 0) + Py_FatalError("Py_Initialize: can't initialize tracemalloc"); + initmain(interp); /* Module __main__ */ if (initstdio() < 0) Py_FatalError( -- cgit v1.2.1 From 7049e92e939bfdb1d9e34a8d3a5d1611d8fd1a4a Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 1 Dec 2013 10:03:26 +0100 Subject: Closes #19831: Stop tracemalloc later at Python shutdown to be able to use tracemalloc in objects destructor Replace atexit handler with an harcoded C function _PyTraceMalloc_Fini(). --- Python/pythonrun.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'Python/pythonrun.c') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 3adbbd7373..ccf82af36b 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -106,6 +106,7 @@ extern int _PyFaulthandler_Init(void); extern void _PyFaulthandler_Fini(void); extern void _PyHash_Fini(void); extern int _PyTraceMalloc_Init(void); +extern int _PyTraceMalloc_Fini(void); #ifdef WITH_THREAD extern void _PyGILState_Init(PyInterpreterState *, PyThreadState *); @@ -642,6 +643,10 @@ Py_Finalize(void) PyGC_Collect(); #endif + /* Disable tracemalloc after all Python objects have been destroyed, + so it is possible to use tracemalloc in objects destructor. */ + _PyTraceMalloc_Fini(); + /* Destroy the database used by _PyImport_{Fixup,Find}Extension */ _PyImport_Fini(); -- cgit v1.2.1