From: Markus Metzger Date: Mon, 11 May 2026 08:53:21 +0000 (+0000) Subject: gdb: use all_threads() in for_each_thread() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f1fdd3164b86d15c97204fe9eaa5de57ae33f2bd;p=thirdparty%2Fbinutils-gdb.git gdb: use all_threads() in for_each_thread() In for_each_thread(), we use all_threads_safe(), which allows deleting the thread. This it not needed in the cases where it is currently used and it causes the iterator to get corrupted when threads are deleted in a nested all_threads_safe() iteration. One such scenario is as follows: - remote debugging in non-stop mode - one thread has hit a breakpoint - one thread exited but GDB does not know about it, yet - resume with 'continue -a' - the continue command uses for_each_thread() to proceed threads individually - the stopped thread starts an inline step-over (displaced stepping disabled) - update_thread_list() learns about the exit and deletes the thread - the safe iterator's m_next still points to the deleted thread Approved-By: Tom Tromey --- diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h index b3052b28d1a..1bdbf621982 100644 --- a/gdb/gdbthread.h +++ b/gdb/gdbthread.h @@ -796,7 +796,14 @@ void thread_change_ptid (process_stratum_target *targ, using for_each_thread_callback_ftype = gdb::function_view; -/* Call CALLBACK once for each known thread. */ +/* Call CALLBACK once for each known thread. + + CALLBACK must not delete the thread. To delete threads, use: + + for (thread_info &t : all_threads_safe ()) + if (some_condition ()) + delete &t; +*/ extern void for_each_thread (for_each_thread_callback_ftype callback); diff --git a/gdb/thread.c b/gdb/thread.c index 4f62ca280cd..110e58a70aa 100644 --- a/gdb/thread.c +++ b/gdb/thread.c @@ -605,7 +605,7 @@ find_thread_by_handle (gdb::array_view handle, void for_each_thread (for_each_thread_callback_ftype callback) { - for (thread_info &tp : all_threads_safe ()) + for (thread_info &tp : all_threads ()) callback (&tp); }