@@ -1095,6 +1095,9 @@ tstate_is_freed(PyThreadState *tstate)
10951095 if (_PyMem_IsPtrFreed (tstate -> interp )) {
10961096 return 1 ;
10971097 }
1098+ if (_PyMem_IsULongFreed (tstate -> thread_id )) {
1099+ return 1 ;
1100+ }
10981101 return 0 ;
10991102}
11001103
@@ -1114,7 +1117,7 @@ dump_traceback(int fd, PyThreadState *tstate, int write_header)
11141117 }
11151118
11161119 if (tstate_is_freed (tstate )) {
1117- PUTS (fd , " <tstate is freed >\n" );
1120+ PUTS (fd , " <freed thread state >\n" );
11181121 return ;
11191122 }
11201123
@@ -1139,12 +1142,16 @@ dump_traceback(int fd, PyThreadState *tstate, int write_header)
11391142 PUTS (fd , " <freed frame>\n" );
11401143 break ;
11411144 }
1145+ // Read frame->previous early since memory can be freed during
1146+ // dump_frame()
1147+ _PyInterpreterFrame * previous = frame -> previous ;
1148+
11421149 if (dump_frame (fd , frame ) < 0 ) {
11431150 PUTS (fd , " <invalid frame>\n" );
11441151 break ;
11451152 }
11461153
1147- frame = frame -> previous ;
1154+ frame = previous ;
11481155 if (frame == NULL ) {
11491156 break ;
11501157 }
@@ -1241,7 +1248,9 @@ write_thread_id(int fd, PyThreadState *tstate, int is_current)
12411248 tstate -> thread_id ,
12421249 sizeof (unsigned long ) * 2 );
12431250
1244- write_thread_name (fd , tstate );
1251+ if (!_PyMem_IsULongFreed (tstate -> thread_id )) {
1252+ write_thread_name (fd , tstate );
1253+ }
12451254
12461255 PUTS (fd , " (most recent call first):\n" );
12471256}
@@ -1299,7 +1308,6 @@ _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
12991308 return "unable to get the thread head state" ;
13001309
13011310 /* Dump the traceback of each thread */
1302- tstate = PyInterpreterState_ThreadHead (interp );
13031311 unsigned int nthreads = 0 ;
13041312 _Py_BEGIN_SUPPRESS_IPH
13051313 do
@@ -1310,11 +1318,18 @@ _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
13101318 PUTS (fd , "...\n" );
13111319 break ;
13121320 }
1321+
1322+ if (tstate_is_freed (tstate )) {
1323+ PUTS (fd , "<freed thread state>\n" );
1324+ break ;
1325+ }
1326+
13131327 write_thread_id (fd , tstate , tstate == current_tstate );
13141328 if (tstate == current_tstate && tstate -> interp -> gc .collecting ) {
13151329 PUTS (fd , " Garbage-collecting\n" );
13161330 }
13171331 dump_traceback (fd , tstate , 0 );
1332+
13181333 tstate = PyThreadState_Next (tstate );
13191334 nthreads ++ ;
13201335 } while (tstate != NULL );
0 commit comments