Improve faulthandler.enable(all_threads=True)

faulthandler.enable(all_threads=True) dumps the tracebacks even if it is not
possible to get the state of the current thread

Create also the get_thread_state() subfunction to factorize the code.
This commit is contained in:
Victor Stinner 2011-04-09 00:47:23 +02:00
parent c790a5346d
commit a4de6d885f
1 changed files with 32 additions and 22 deletions

View File

@ -40,6 +40,7 @@ static struct {
PyObject *file;
int fd;
int all_threads;
PyInterpreterState *interp;
} fatal_error = {0, NULL, -1, 0};
#ifdef FAULTHANDLER_LATER
@ -165,6 +166,20 @@ faulthandler_get_fileno(PyObject *file, int *p_fd)
return file;
}
/* Get the state of the current thread: only call this function if the current
thread holds the GIL. Raise an exception on error. */
static PyThreadState*
get_thread_state(void)
{
PyThreadState *tstate = PyThreadState_Get();
if (tstate == NULL) {
PyErr_SetString(PyExc_RuntimeError,
"unable to get the current thread state");
return NULL;
}
return tstate;
}
static PyObject*
faulthandler_dump_traceback_py(PyObject *self,
PyObject *args, PyObject *kwargs)
@ -185,13 +200,9 @@ faulthandler_dump_traceback_py(PyObject *self,
if (file == NULL)
return NULL;
/* The caller holds the GIL and so PyThreadState_Get() can be used */
tstate = PyThreadState_Get();
if (tstate == NULL) {
PyErr_SetString(PyExc_RuntimeError,
"unable to get the current thread state");
tstate = get_thread_state();
if (tstate == NULL)
return NULL;
}
if (all_threads) {
errmsg = _Py_DumpTracebackThreads(fd, tstate->interp, tstate);
@ -266,13 +277,13 @@ faulthandler_fatal_error(int signum)
#else
tstate = PyThreadState_Get();
#endif
if (tstate == NULL)
return;
if (fatal_error.all_threads)
_Py_DumpTracebackThreads(fd, tstate->interp, tstate);
else
_Py_DumpTraceback(fd, tstate);
_Py_DumpTracebackThreads(fd, fatal_error.interp, tstate);
else {
if (tstate != NULL)
_Py_DumpTraceback(fd, tstate);
}
#ifdef MS_WINDOWS
if (signum == SIGSEGV) {
@ -301,6 +312,7 @@ faulthandler_enable(PyObject *self, PyObject *args, PyObject *kwargs)
#endif
int err;
int fd;
PyThreadState *tstate;
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"|Oi:enable", kwlist, &file, &all_threads))
@ -310,11 +322,16 @@ faulthandler_enable(PyObject *self, PyObject *args, PyObject *kwargs)
if (file == NULL)
return NULL;
tstate = get_thread_state();
if (tstate == NULL)
return NULL;
Py_XDECREF(fatal_error.file);
Py_INCREF(file);
fatal_error.file = file;
fatal_error.fd = fd;
fatal_error.all_threads = all_threads;
fatal_error.interp = tstate->interp;
if (!fatal_error.enabled) {
fatal_error.enabled = 1;
@ -515,12 +532,9 @@ faulthandler_dump_tracebacks_later(PyObject *self,
return NULL;
}
tstate = PyThreadState_Get();
if (tstate == NULL) {
PyErr_SetString(PyExc_RuntimeError,
"unable to get the current thread state");
tstate = get_thread_state();
if (tstate == NULL)
return NULL;
}
file = faulthandler_get_fileno(file, &fd);
if (file == NULL)
@ -652,13 +666,9 @@ faulthandler_register(PyObject *self,
if (!check_signum(signum))
return NULL;
/* The caller holds the GIL and so PyThreadState_Get() can be used */
tstate = PyThreadState_Get();
if (tstate == NULL) {
PyErr_SetString(PyExc_RuntimeError,
"unable to get the current thread state");
tstate = get_thread_state();
if (tstate == NULL)
return NULL;
}
file = faulthandler_get_fileno(file, &fd);
if (file == NULL)