@@ -1094,6 +1094,9 @@ tstate_is_freed(PyThreadState *tstate)
10941094 if (_PyMem_IsPtrFreed (tstate -> interp )) {
10951095 return 1 ;
10961096 }
1097+ if (_PyMem_IsULongFreed (tstate -> thread_id )) {
1098+ return 1 ;
1099+ }
10971100 return 0 ;
10981101}
10991102
@@ -1113,7 +1116,7 @@ dump_traceback(int fd, PyThreadState *tstate, int write_header)
11131116 }
11141117
11151118 if (tstate_is_freed (tstate )) {
1116- PUTS (fd , " <tstate is freed >\n" );
1119+ PUTS (fd , " <freed thread state >\n" );
11171120 return ;
11181121 }
11191122
@@ -1138,12 +1141,16 @@ dump_traceback(int fd, PyThreadState *tstate, int write_header)
11381141 PUTS (fd , " <freed frame>\n" );
11391142 break ;
11401143 }
1144+ // Read frame->previous early since memory can be freed during
1145+ // dump_frame()
1146+ _PyInterpreterFrame * previous = frame -> previous ;
1147+
11411148 if (dump_frame (fd , frame ) < 0 ) {
11421149 PUTS (fd , " <invalid frame>\n" );
11431150 break ;
11441151 }
11451152
1146- frame = frame -> previous ;
1153+ frame = previous ;
11471154 if (frame == NULL ) {
11481155 break ;
11491156 }
@@ -1240,7 +1247,9 @@ write_thread_id(int fd, PyThreadState *tstate, int is_current)
12401247 tstate -> thread_id ,
12411248 sizeof (unsigned long ) * 2 );
12421249
1243- write_thread_name (fd , tstate );
1250+ if (!_PyMem_IsULongFreed (tstate -> thread_id )) {
1251+ write_thread_name (fd , tstate );
1252+ }
12441253
12451254 PUTS (fd , " (most recent call first):\n" );
12461255}
@@ -1298,7 +1307,6 @@ _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
12981307 return "unable to get the thread head state" ;
12991308
13001309 /* Dump the traceback of each thread */
1301- tstate = PyInterpreterState_ThreadHead (interp );
13021310 unsigned int nthreads = 0 ;
13031311 _Py_BEGIN_SUPPRESS_IPH
13041312 do
@@ -1309,11 +1317,18 @@ _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
13091317 PUTS (fd , "...\n" );
13101318 break ;
13111319 }
1320+
1321+ if (tstate_is_freed (tstate )) {
1322+ PUTS (fd , "<freed thread state>\n" );
1323+ break ;
1324+ }
1325+
13121326 write_thread_id (fd , tstate , tstate == current_tstate );
13131327 if (tstate == current_tstate && tstate -> interp -> gc .collecting ) {
13141328 PUTS (fd , " Garbage-collecting\n" );
13151329 }
13161330 dump_traceback (fd , tstate , 0 );
1331+
13171332 tstate = PyThreadState_Next (tstate );
13181333 nthreads ++ ;
13191334 } while (tstate != NULL );
0 commit comments