@@ -960,6 +960,9 @@ tstate_is_freed(PyThreadState *tstate)
960960 if (_PyMem_IsPtrFreed (tstate -> interp )) {
961961 return 1 ;
962962 }
963+ if (_PyMem_IsULongFreed (tstate -> thread_id )) {
964+ return 1 ;
965+ }
963966 return 0 ;
964967}
965968
@@ -979,7 +982,7 @@ dump_traceback(int fd, PyThreadState *tstate, int write_header)
979982 }
980983
981984 if (tstate_is_freed (tstate )) {
982- PUTS (fd , " <tstate is freed >\n" );
985+ PUTS (fd , " <freed thread state >\n" );
983986 return ;
984987 }
985988
@@ -1004,12 +1007,16 @@ dump_traceback(int fd, PyThreadState *tstate, int write_header)
10041007 PUTS (fd , " <freed frame>\n" );
10051008 break ;
10061009 }
1010+ // Read frame->previous early since memory can be freed during
1011+ // dump_frame()
1012+ _PyInterpreterFrame * previous = frame -> previous ;
1013+
10071014 if (dump_frame (fd , frame ) < 0 ) {
10081015 PUTS (fd , " <invalid frame>\n" );
10091016 break ;
10101017 }
10111018
1012- frame = frame -> previous ;
1019+ frame = previous ;
10131020 if (frame == NULL ) {
10141021 break ;
10151022 }
@@ -1100,7 +1107,6 @@ _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
11001107 return "unable to get the thread head state" ;
11011108
11021109 /* Dump the traceback of each thread */
1103- tstate = PyInterpreterState_ThreadHead (interp );
11041110 unsigned int nthreads = 0 ;
11051111 _Py_BEGIN_SUPPRESS_IPH
11061112 do
@@ -1111,11 +1117,18 @@ _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
11111117 PUTS (fd , "...\n" );
11121118 break ;
11131119 }
1120+
1121+ if (tstate_is_freed (tstate )) {
1122+ PUTS (fd , "<freed thread state>\n" );
1123+ break ;
1124+ }
1125+
11141126 write_thread_id (fd , tstate , tstate == current_tstate );
11151127 if (tstate == current_tstate && tstate -> interp -> gc .collecting ) {
11161128 PUTS (fd , " Garbage-collecting\n" );
11171129 }
11181130 dump_traceback (fd , tstate , 0 );
1131+
11191132 tstate = PyThreadState_Next (tstate );
11201133 nthreads ++ ;
11211134 } while (tstate != NULL );
0 commit comments