@@ -229,7 +229,7 @@ ssize_t insert_thread(pthread_t tid, ssize_t i)
229229{
230230 assert (signal_type == SIGALRM );
231231 i = search_thread (tid , i );
232- if (i > 0 )
232+ if (i >= 0 )
233233 return -1 ;
234234 if (thread_count == threads_size ) {
235235 threads_size += threads_size_step ;
@@ -268,6 +268,45 @@ ssize_t remove_threads(void)
268268 return 0 ;
269269}
270270
271+ #ifndef RPYTHON_VMPROF
272+ static int python_thread_is_alive (pthread_t tid )
273+ {
274+ unsigned long ident = (unsigned long )tid ; /* as PyThread_get_thread_ident */
275+ PyInterpreterState * istate = PyInterpreterState_Head ();
276+ PyThreadState * state ;
277+ while (istate != NULL ) {
278+ state = PyInterpreterState_ThreadHead (istate );
279+ while (state != NULL ) {
280+ if (state -> thread_id == ident )
281+ return 1 ;
282+ state = PyThreadState_Next (state );
283+ }
284+ istate = PyInterpreterState_Next (istate );
285+ }
286+ return 0 ;
287+ }
288+
289+ void prune_dead_threads (void )
290+ {
291+ /* pthread_kill() on a thread that has exited and been joined is
292+ undefined behaviour, and segfaults on glibc because the thread
293+ descriptor lives on the thread's freed stack. Nothing removes an
294+ exited thread from 'threads' by itself, so before broadcasting drop
295+ every registered thread whose Python thread state is gone: CPython
296+ deletes it before the thread exits. Called from the signal handler,
297+ under the spinlock and the SIGSEGV guard that also protects the
298+ thread state lookup. */
299+ size_t i = 0 ;
300+ while (i < thread_count ) {
301+ if (python_thread_is_alive (threads [i ])) {
302+ i ++ ;
303+ } else {
304+ remove_thread (threads [i ], i );
305+ }
306+ }
307+ }
308+ #endif
309+
271310int broadcast_signal_for_threads (void )
272311{
273312 int done = 1 ;
@@ -279,7 +318,9 @@ int broadcast_signal_for_threads(void)
279318 if (pthread_equal (tid , self )) {
280319 done = 0 ;
281320 } else if (pthread_kill (tid , SIGALRM )) {
321+ /* the last entry is moved into slot i, look at it next */
282322 remove_thread (tid , i );
323+ continue ;
283324 }
284325 i ++ ;
285326 }
0 commit comments