From 84092ac3705ffe371f5f1ec8ecc8c2830861ba9e Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 25 Mar 2015 01:54:46 +0100 Subject: Issue #23571: Fix reentrant call to Py_FatalError() Flushing sys.stdout and sys.stderr in Py_FatalError() can call again Py_FatalError(). Add a reentrant flag to detect this case and just abort at the second call. --- Python/pythonrun.c | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/Python/pythonrun.c b/Python/pythonrun.c index c16ebc4..9b2405f 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -2663,6 +2663,19 @@ void Py_FatalError(const char *msg) { const int fd = fileno(stderr); + static int reentrant = 0; +#ifdef MS_WINDOWS + size_t len; + WCHAR* buffer; + size_t i; +#endif + + if (reentrant) { + /* Py_FatalError() caused a second fatal error. + Example: flush_std_files() raises a recursion error. */ + goto exit; + } + reentrant = 1; fprintf(stderr, "Fatal Python error: %s\n", msg); fflush(stderr); /* it helps in Windows debug build */ @@ -2680,25 +2693,23 @@ Py_FatalError(const char *msg) _PyFaulthandler_Fini(); #ifdef MS_WINDOWS - { - size_t len = strlen(msg); - WCHAR* buffer; - size_t i; - - /* Convert the message to wchar_t. This uses a simple one-to-one - conversion, assuming that the this error message actually uses ASCII - only. If this ceases to be true, we will have to convert. */ - buffer = alloca( (len+1) * (sizeof *buffer)); - for( i=0; i<=len; ++i) - buffer[i] = msg[i]; - OutputDebugStringW(L"Fatal Python error: "); - OutputDebugStringW(buffer); - OutputDebugStringW(L"\n"); - } -#ifdef _DEBUG + len = strlen(msg); + + /* Convert the message to wchar_t. This uses a simple one-to-one + conversion, assuming that the this error message actually uses ASCII + only. If this ceases to be true, we will have to convert. */ + buffer = alloca( (len+1) * (sizeof *buffer)); + for( i=0; i<=len; ++i) + buffer[i] = msg[i]; + OutputDebugStringW(L"Fatal Python error: "); + OutputDebugStringW(buffer); + OutputDebugStringW(L"\n"); +#endif /* MS_WINDOWS */ + +exit: +#if defined(MS_WINDOWS) && defined(_DEBUG) DebugBreak(); #endif -#endif /* MS_WINDOWS */ abort(); } -- cgit v0.12