@@ -69,6 +69,13 @@ class traceback "PyTracebackObject *" "&PyTraceback_Type"
6969
7070#include "clinic/traceback.c.h"
7171
72+
73+ #ifdef MS_WINDOWS
74+ typedef HRESULT (WINAPI * PF_GET_THREAD_DESCRIPTION )(HANDLE , PCWSTR * );
75+ static PF_GET_THREAD_DESCRIPTION pGetThreadDescription = NULL ;
76+ #endif
77+
78+
7279static PyObject *
7380tb_create_raw (PyTracebackObject * next , PyFrameObject * frame , int lasti ,
7481 int lineno )
@@ -1107,23 +1114,12 @@ _Py_DumpTraceback(int fd, PyThreadState *tstate)
11071114# endif
11081115#endif
11091116
1110- /* Write the thread identifier into the file 'fd': "Current thread 0xHHHH:\" if
1111- is_current is true, "Thread 0xHHHH:\n" otherwise.
1112-
1113- This function is signal safe. */
11141117
1118+ // Write the thread name
11151119static void
1116- write_thread_id (int fd , PyThreadState * tstate , int is_current )
1120+ write_thread_name (int fd , PyThreadState * tstate )
11171121{
1118- if (is_current )
1119- PUTS (fd , "Current thread 0x" );
1120- else
1121- PUTS (fd , "Thread 0x" );
1122- _Py_DumpHexadecimal (fd ,
1123- tstate -> thread_id ,
1124- sizeof (unsigned long ) * 2 );
1125-
1126- // Write the thread name
1122+ #ifndef MS_WINDOWS
11271123#if defined(HAVE_PTHREAD_GETNAME_NP ) || defined(HAVE_PTHREAD_GET_NAME_NP )
11281124 char name [100 ];
11291125 pthread_t thread = (pthread_t )tstate -> thread_id ;
@@ -1142,6 +1138,54 @@ write_thread_id(int fd, PyThreadState *tstate, int is_current)
11421138 }
11431139 }
11441140#endif
1141+ #else
1142+ // Windows implementation
1143+ if (pGetThreadDescription == NULL ) {
1144+ return ;
1145+ }
1146+
1147+ HANDLE thread = OpenThread (THREAD_QUERY_LIMITED_INFORMATION , FALSE, tstate -> thread_id );
1148+ if (thread == NULL ) {
1149+ return ;
1150+ }
1151+
1152+ wchar_t * wname ;
1153+ HRESULT hr = pGetThreadDescription (thread , & wname );
1154+ if (!FAILED (hr )) {
1155+ char * name = _Py_EncodeLocaleRaw (wname , NULL );
1156+ if (name != NULL ) {
1157+ size_t len = strlen (name );
1158+ if (len ) {
1159+ PUTS (fd , " [" );
1160+ (void )_Py_write_noraise (fd , name , len );
1161+ PUTS (fd , "]" );
1162+ }
1163+ PyMem_RawFree (name );
1164+ }
1165+ LocalFree (wname );
1166+ }
1167+ CloseHandle (thread );
1168+ #endif
1169+ }
1170+
1171+
1172+ /* Write the thread identifier into the file 'fd': "Current thread 0xHHHH:\" if
1173+ is_current is true, "Thread 0xHHHH:\n" otherwise.
1174+
1175+ This function is signal safe (except on Windows). */
1176+
1177+ static void
1178+ write_thread_id (int fd , PyThreadState * tstate , int is_current )
1179+ {
1180+ if (is_current )
1181+ PUTS (fd , "Current thread 0x" );
1182+ else
1183+ PUTS (fd , "Thread 0x" );
1184+ _Py_DumpHexadecimal (fd ,
1185+ tstate -> thread_id ,
1186+ sizeof (unsigned long ) * 2 );
1187+
1188+ write_thread_name (fd , tstate );
11451189
11461190 PUTS (fd , " (most recent call first):\n" );
11471191}
@@ -1336,3 +1380,20 @@ _Py_InitDumpStack(void)
13361380 (void )backtrace (callstack , 1 );
13371381#endif
13381382}
1383+
1384+
1385+ void
1386+ _Py_DumpTraceback_Init (void )
1387+ {
1388+ #ifdef MS_WINDOWS
1389+ if (pGetThreadDescription != NULL ) {
1390+ return ;
1391+ }
1392+
1393+ HMODULE kernelbase = GetModuleHandleW (L"kernelbase.dll" );
1394+ if (kernelbase != NULL ) {
1395+ pGetThreadDescription = (PF_GET_THREAD_DESCRIPTION )GetProcAddress (
1396+ kernelbase , "GetThreadDescription" );
1397+ }
1398+ #endif
1399+ }
0 commit comments