diff -r 8ec4acfdb851 Modules/faulthandler.c --- a/Modules/faulthandler.c Wed Apr 01 11:09:43 2015 +0200 +++ b/Modules/faulthandler.c Wed Apr 01 11:43:50 2015 +0200 @@ -28,9 +28,7 @@ # define FAULTHANDLER_USER #endif -/* cast size_t to int because write() takes an int on Windows - (anyway, the length is smaller than 30 characters) */ -#define PUTS(fd, str) write(fd, str, (int)strlen(str)) +#define PUTS(fd, str) _Py_write_noraise(fd, str, strlen(str)) _Py_IDENTIFIER(enable); _Py_IDENTIFIER(fileno); @@ -247,6 +245,10 @@ faulthandler_dump_traceback_py(PyObject else { _Py_DumpTraceback(fd, tstate); } + + if (PyErr_CheckSignals()) + return NULL; + Py_RETURN_NONE; } @@ -272,6 +274,7 @@ faulthandler_fatal_error(int signum) fault_handler_t *handler = NULL; PyThreadState *tstate; int save_errno = errno; + static volatile int reentrant = 0; if (!fatal_error.enabled) return; @@ -294,29 +297,35 @@ faulthandler_fatal_error(int signum) #endif handler->enabled = 0; - PUTS(fd, "Fatal Python error: "); - PUTS(fd, handler->name); - PUTS(fd, "\n\n"); + if (!reentrant) { + reentrant = 1; + + PUTS(fd, "Fatal Python error: "); + PUTS(fd, handler->name); + PUTS(fd, "\n\n"); #ifdef WITH_THREAD - /* SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL are synchronous signals and - are thus delivered to the thread that caused the fault. Get the Python - thread state of the current thread. + /* SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL are synchronous signals and + are thus delivered to the thread that caused the fault. Get the Python + thread state of the current thread. - PyThreadState_Get() doesn't give the state of the thread that caused the - fault if the thread released the GIL, and so this function cannot be - used. Read the thread local storage (TLS) instead: call - PyGILState_GetThisThreadState(). */ - tstate = PyGILState_GetThisThreadState(); + PyThreadState_Get() doesn't give the state of the thread that caused the + fault if the thread released the GIL, and so this function cannot be + used. Read the thread local storage (TLS) instead: call + PyGILState_GetThisThreadState(). */ + tstate = PyGILState_GetThisThreadState(); #else - tstate = PyThreadState_Get(); + tstate = PyThreadState_Get(); #endif - if (fatal_error.all_threads) - _Py_DumpTracebackThreads(fd, fatal_error.interp, tstate); - else { - if (tstate != NULL) - _Py_DumpTraceback(fd, tstate); + if (fatal_error.all_threads) + _Py_DumpTracebackThreads(fd, fatal_error.interp, tstate); + else { + if (tstate != NULL) + _Py_DumpTraceback(fd, tstate); + } + + reentrant = 0; } errno = save_errno; @@ -474,7 +483,7 @@ faulthandler_thread(void *unused) /* get the thread holding the GIL, NULL if no thread hold the GIL */ current = (PyThreadState*)_Py_atomic_load_relaxed(&_PyThreadState_Current); - write(thread.fd, thread.header, (int)thread.header_len); + _Py_write_noraise(thread.fd, thread.header, (int)thread.header_len); errmsg = _Py_DumpTracebackThreads(thread.fd, thread.interp, current); ok = (errmsg == NULL); @@ -662,26 +671,34 @@ faulthandler_user(int signum) user_signal_t *user; PyThreadState *tstate; int save_errno = errno; + static volatile int reentrant = 0; user = &user_signals[signum]; if (!user->enabled) return; + if (!reentrant) { + reentrant = 1; + #ifdef WITH_THREAD - /* PyThreadState_Get() doesn't give the state of the current thread if - the thread doesn't hold the GIL. Read the thread local storage (TLS) - instead: call PyGILState_GetThisThreadState(). */ - tstate = PyGILState_GetThisThreadState(); + /* PyThreadState_Get() doesn't give the state of the current thread if + the thread doesn't hold the GIL. Read the thread local storage (TLS) + instead: call PyGILState_GetThisThreadState(). */ + tstate = PyGILState_GetThisThreadState(); #else - tstate = PyThreadState_Get(); + tstate = PyThreadState_Get(); #endif - if (user->all_threads) - _Py_DumpTracebackThreads(user->fd, user->interp, tstate); - else { - if (tstate != NULL) - _Py_DumpTraceback(user->fd, tstate); + if (user->all_threads) + _Py_DumpTracebackThreads(user->fd, user->interp, tstate); + else { + if (tstate != NULL) + _Py_DumpTraceback(user->fd, tstate); + } + + reentrant = 0; } + #ifdef HAVE_SIGACTION if (user->chain) { (void)sigaction(signum, &user->previous, NULL);