mirror of
https://github.com/python/cpython.git
synced 2025-11-01 06:01:29 +00:00
gh-125434: Display thread name in faulthandler on Windows (#140675)
This commit is contained in:
parent
1753ccb432
commit
313145eab5
4 changed files with 80 additions and 14 deletions
|
|
@ -506,6 +506,7 @@ pycore_init_runtime(_PyRuntimeState *runtime,
|
|||
_PyRuntimeState_SetFinalizing(runtime, NULL);
|
||||
|
||||
_Py_InitVersion();
|
||||
_Py_DumpTraceback_Init();
|
||||
|
||||
status = _Py_HashRandomization_Init(config);
|
||||
if (_PyStatus_EXCEPTION(status)) {
|
||||
|
|
|
|||
|
|
@ -69,6 +69,13 @@ class traceback "PyTracebackObject *" "&PyTraceback_Type"
|
|||
|
||||
#include "clinic/traceback.c.h"
|
||||
|
||||
|
||||
#ifdef MS_WINDOWS
|
||||
typedef HRESULT (WINAPI *PF_GET_THREAD_DESCRIPTION)(HANDLE, PCWSTR*);
|
||||
static PF_GET_THREAD_DESCRIPTION pGetThreadDescription = NULL;
|
||||
#endif
|
||||
|
||||
|
||||
static PyObject *
|
||||
tb_create_raw(PyTracebackObject *next, PyFrameObject *frame, int lasti,
|
||||
int lineno)
|
||||
|
|
@ -1107,23 +1114,12 @@ _Py_DumpTraceback(int fd, PyThreadState *tstate)
|
|||
# endif
|
||||
#endif
|
||||
|
||||
/* Write the thread identifier into the file 'fd': "Current thread 0xHHHH:\" if
|
||||
is_current is true, "Thread 0xHHHH:\n" otherwise.
|
||||
|
||||
This function is signal safe. */
|
||||
|
||||
// Write the thread name
|
||||
static void
|
||||
write_thread_id(int fd, PyThreadState *tstate, int is_current)
|
||||
write_thread_name(int fd, PyThreadState *tstate)
|
||||
{
|
||||
if (is_current)
|
||||
PUTS(fd, "Current thread 0x");
|
||||
else
|
||||
PUTS(fd, "Thread 0x");
|
||||
_Py_DumpHexadecimal(fd,
|
||||
tstate->thread_id,
|
||||
sizeof(unsigned long) * 2);
|
||||
|
||||
// Write the thread name
|
||||
#ifndef MS_WINDOWS
|
||||
#if defined(HAVE_PTHREAD_GETNAME_NP) || defined(HAVE_PTHREAD_GET_NAME_NP)
|
||||
char name[100];
|
||||
pthread_t thread = (pthread_t)tstate->thread_id;
|
||||
|
|
@ -1142,6 +1138,54 @@ write_thread_id(int fd, PyThreadState *tstate, int is_current)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
// Windows implementation
|
||||
if (pGetThreadDescription == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
HANDLE thread = OpenThread(THREAD_QUERY_LIMITED_INFORMATION, FALSE, tstate->thread_id);
|
||||
if (thread == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
wchar_t *wname;
|
||||
HRESULT hr = pGetThreadDescription(thread, &wname);
|
||||
if (!FAILED(hr)) {
|
||||
char *name = _Py_EncodeLocaleRaw(wname, NULL);
|
||||
if (name != NULL) {
|
||||
size_t len = strlen(name);
|
||||
if (len) {
|
||||
PUTS(fd, " [");
|
||||
(void)_Py_write_noraise(fd, name, len);
|
||||
PUTS(fd, "]");
|
||||
}
|
||||
PyMem_RawFree(name);
|
||||
}
|
||||
LocalFree(wname);
|
||||
}
|
||||
CloseHandle(thread);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Write the thread identifier into the file 'fd': "Current thread 0xHHHH:\" if
|
||||
is_current is true, "Thread 0xHHHH:\n" otherwise.
|
||||
|
||||
This function is signal safe (except on Windows). */
|
||||
|
||||
static void
|
||||
write_thread_id(int fd, PyThreadState *tstate, int is_current)
|
||||
{
|
||||
if (is_current)
|
||||
PUTS(fd, "Current thread 0x");
|
||||
else
|
||||
PUTS(fd, "Thread 0x");
|
||||
_Py_DumpHexadecimal(fd,
|
||||
tstate->thread_id,
|
||||
sizeof(unsigned long) * 2);
|
||||
|
||||
write_thread_name(fd, tstate);
|
||||
|
||||
PUTS(fd, " (most recent call first):\n");
|
||||
}
|
||||
|
|
@ -1336,3 +1380,20 @@ _Py_InitDumpStack(void)
|
|||
(void)backtrace(callstack, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_Py_DumpTraceback_Init(void)
|
||||
{
|
||||
#ifdef MS_WINDOWS
|
||||
if (pGetThreadDescription != NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
HMODULE kernelbase = GetModuleHandleW(L"kernelbase.dll");
|
||||
if (kernelbase != NULL) {
|
||||
pGetThreadDescription = (PF_GET_THREAD_DESCRIPTION)GetProcAddress(
|
||||
kernelbase, "GetThreadDescription");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue