diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2016-03-16 21:45:24 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2016-03-16 21:45:24 (GMT) |
commit | 861d9abfcf6a4a34790e4edc5e440a68534137e1 (patch) | |
tree | a4ea3ef14a2f0494743733b9db4079f27f5906ca /Python/traceback.c | |
parent | c36674a2c52ecb30e180b3bcced2b8c529cf72fb (diff) | |
download | cpython-861d9abfcf6a4a34790e4edc5e440a68534137e1.zip cpython-861d9abfcf6a4a34790e4edc5e440a68534137e1.tar.gz cpython-861d9abfcf6a4a34790e4edc5e440a68534137e1.tar.bz2 |
faulthandler now works in non-Python threads
Issue #26563:
* Add _PyGILState_GetInterpreterStateUnsafe() function: the single
PyInterpreterState used by this process' GILState implementation.
* Enhance _Py_DumpTracebackThreads() to retrieve the interpreter state from
autoInterpreterState in last resort. The function now accepts NULL for interp
and current_tstate parameters.
* test_faulthandler: fix a ResourceWarning when test is interrupted by CTRL+c
Diffstat (limited to 'Python/traceback.c')
-rw-r--r-- | Python/traceback.c | 49 |
1 files changed, 47 insertions, 2 deletions
diff --git a/Python/traceback.c b/Python/traceback.c index 8383c16..403dba5 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -707,11 +707,56 @@ write_thread_id(int fd, PyThreadState *tstate, int is_current) handlers if signals were received. */ const char* _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp, - PyThreadState *current_thread) + PyThreadState *current_tstate) { PyThreadState *tstate; unsigned int nthreads; +#ifdef WITH_THREAD + if (current_tstate == NULL) { + /* _Py_DumpTracebackThreads() is called from signal handlers by + faulthandler. + + 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(). */ + current_tstate = PyGILState_GetThisThreadState(); + } + + if (interp == NULL) { + if (current_tstate == NULL) { + interp = _PyGILState_GetInterpreterStateUnsafe(); + if (interp == NULL) { + /* We need the interpreter state to get Python threads */ + return "unable to get the interpreter state"; + } + } + else { + interp = current_tstate->interp; + } + } +#else + if (current_tstate == NULL) { + /* Call _PyThreadState_UncheckedGet() instead of PyThreadState_Get() + to not fail with a fatal error if the thread state is NULL. */ + current_thread = _PyThreadState_UncheckedGet(); + } + + if (interp == NULL) { + if (current_tstate == NULL) { + /* We need the interpreter state to get Python threads */ + return "unable to get the interpreter state"; + } + interp = current_tstate->interp; + } +#endif + assert(interp != NULL); + /* Get the current interpreter from the current thread */ tstate = PyInterpreterState_ThreadHead(interp); if (tstate == NULL) @@ -729,7 +774,7 @@ _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp, PUTS(fd, "...\n"); break; } - write_thread_id(fd, tstate, tstate == current_thread); + write_thread_id(fd, tstate, tstate == current_tstate); dump_traceback(fd, tstate, 0); tstate = PyThreadState_Next(tstate); nthreads++; |