- struct thread_info **tp_array;
- struct thread_info *tp;
- int i = 0, k;
-
- /* Save a copy of the thread_list in case we execute detach
- command. */
- tp_array = XNEWVEC (struct thread_info *, tc);
- make_cleanup (xfree, tp_array);
-
- ALL_NON_EXITED_THREADS (tp)
- {
- tp_array[i] = tp;
- tp->refcount++;
- i++;
- }
- /* Because we skipped exited threads, we may end up with fewer
- threads in the array than the total count of threads. */
- gdb_assert (i <= tc);
-
- if (i != 0)
- qsort (tp_array, i, sizeof (*tp_array), tp_array_compar);
-
- ta_cleanup.tp_array = tp_array;
- ta_cleanup.count = i;
- make_cleanup (set_thread_refcount, &ta_cleanup);
-
- for (k = 0; k != i; k++)
- if (thread_alive (tp_array[k]))
- {
- switch_to_thread (tp_array[k]->ptid);
- printf_filtered (_("\nThread %s (%s):\n"),
- print_thread_id (tp_array[k]),
+ /* Save a copy of the thread list and increment each thread's
+ refcount while executing the command in the context of each
+ thread, in case the command is one that wipes threads. E.g.,
+ detach, kill, disconnect, etc., or even normally continuing
+ over an inferior or thread exit. */
+ std::vector<thread_info *> thr_list_cpy;
+ thr_list_cpy.reserve (tc);
+
+ {
+ thread_info *tp;
+
+ ALL_NON_EXITED_THREADS (tp)
+ {
+ thr_list_cpy.push_back (tp);
+ }
+
+ gdb_assert (thr_list_cpy.size () == tc);
+ }
+
+ /* Increment the refcounts, and restore them back on scope
+ exit. */
+ scoped_inc_dec_ref inc_dec_ref (thr_list_cpy);
+
+ std::sort (thr_list_cpy.begin (), thr_list_cpy.end (), tp_array_compar);
+
+ scoped_restore_current_thread restore_thread;
+
+ for (thread_info *thr : thr_list_cpy)
+ if (thread_alive (thr))
+ {
+ switch_to_thread (thr->ptid);
+ printf_filtered (_("\nThread %s (%s):\n"),
+ print_thread_id (thr),