diff --git a/Python/pystate.c b/Python/pystate.c index a18a159b551..18dd3276f00 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -231,7 +231,7 @@ PyStatus _PyInterpreterState_Enable(_PyRuntimeState *runtime) { struct pyinterpreters *interpreters = &runtime->interpreters; - interpreters->next_id = 0; + interpreters->next_id = 1; /* Py_Finalize() calls _PyRuntimeState_Fini() which clears the mutex. Create a new mutex if needed. */ @@ -350,7 +350,7 @@ PyInterpreterState_New(void) if (old_head == NULL) { // We are creating the main interpreter. assert(interpreters->main == NULL); - assert(id == 0); + assert(id == 1); interp = &runtime->_main_interpreter; assert(interp->id == 0); diff --git a/Python/traceback.c b/Python/traceback.c index 4d6cbaae8da..86c6853369c 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -25,9 +25,14 @@ #define OFF(x) offsetof(PyTracebackObject, x) #define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str)) +// Maximum string length (characters) #define MAX_STRING_LENGTH 500 +// Maximum number of frames per thread #define MAX_FRAME_DEPTH 100 +// Maximum number of threads #define MAX_NTHREADS 100 +// Maximum number of interpreters +#define MAX_NINTERP 100 /* Function from Parser/tokenizer.c */ extern char* _PyTokenizer_FindEncodingFilename(int, PyObject *); @@ -1252,13 +1257,16 @@ static void write_thread_id(int fd, PyThreadState *tstate, int is_current) { if (is_current) - PUTS(fd, "Current thread 0x"); + PUTS(fd, "Current thread"); else - PUTS(fd, "Thread 0x"); + PUTS(fd, "Thread"); + PUTS(fd, " #"); + _Py_DumpDecimal(fd, tstate->id); + PUTS(fd, " (0x"); _Py_DumpHexadecimal(fd, tstate->thread_id, sizeof(unsigned long) * 2); - PUTS(fd, " (most recent call first):\n"); + PUTS(fd, ") (most recent call first):\n"); } /* Dump the traceback of all Python threads into fd. Use write() to write the @@ -1268,7 +1276,7 @@ write_thread_id(int fd, PyThreadState *tstate, int is_current) The caller is responsible to call PyErr_CheckSignals() to call Python signal handlers if signals were received. */ const char* -_Py_DumpTracebackThreads(int fd, PyInterpreterState *interp, +_Py_DumpTracebackThreads(int fd, PyInterpreterState *current_interp, PyThreadState *current_tstate) { PyThreadState *tstate; @@ -1289,46 +1297,65 @@ _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp, current_tstate = PyGILState_GetThisThreadState(); } - if (interp == NULL) { + if (current_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"; - } + current_interp = _PyGILState_GetInterpreterStateUnsafe(); } else { - interp = current_tstate->interp; + current_interp = current_tstate->interp; } } - assert(interp != NULL); - - /* Get the current interpreter from the current thread */ - tstate = PyInterpreterState_ThreadHead(interp); - if (tstate == NULL) - return "unable to get the thread head state"; - /* Dump the traceback of each thread */ - tstate = PyInterpreterState_ThreadHead(interp); - nthreads = 0; - _Py_BEGIN_SUPPRESS_IPH - do - { - if (nthreads != 0) + _PyRuntimeState *runtime = &_PyRuntime; + PyInterpreterState *interp = runtime->interpreters.head; + int space = 0; + for (; interp != NULL; interp = interp->next) { + if (space) { PUTS(fd, "\n"); - if (nthreads >= MAX_NTHREADS) { - PUTS(fd, "...\n"); - break; } - write_thread_id(fd, tstate, tstate == current_tstate); - if (tstate == current_tstate && tstate->interp->gc.collecting) { - PUTS(fd, " Garbage-collecting\n"); + space = 1; + + PUTS(fd, "=== "); + if (interp == current_interp) { + PUTS(fd, "Current interpreter"); } - dump_traceback(fd, tstate, 0); - tstate = PyThreadState_Next(tstate); - nthreads++; - } while (tstate != NULL); - _Py_END_SUPPRESS_IPH + else { + PUTS(fd, "Interpreter"); + } + PUTS(fd, " #"); + _Py_DumpDecimal(fd, interp->id); + + PUTS(fd, " (0x"); + _Py_DumpHexadecimal(fd, (uintptr_t)interp, sizeof(uintptr_t) * 2); + PUTS(fd, ") ===\n\n"); + + /* Get the current interpreter from the current thread */ + tstate = PyInterpreterState_ThreadHead(interp); + if (tstate == NULL) + return "unable to get the thread head state"; + + /* Dump the traceback of each thread */ + tstate = PyInterpreterState_ThreadHead(interp); + nthreads = 0; + _Py_BEGIN_SUPPRESS_IPH + do + { + if (nthreads != 0) + PUTS(fd, "\n"); + if (nthreads >= MAX_NTHREADS) { + PUTS(fd, "...\n"); + break; + } + write_thread_id(fd, tstate, tstate == current_tstate); + if (tstate == current_tstate && tstate->interp->gc.collecting) { + PUTS(fd, " Garbage-collecting\n"); + } + dump_traceback(fd, tstate, 0); + tstate = PyThreadState_Next(tstate); + nthreads++; + } while (tstate != NULL); + _Py_END_SUPPRESS_IPH + } return NULL; }