aboutsummaryrefslogtreecommitdiff
path: root/gdb/infrun.c
diff options
context:
space:
mode:
authorPedro Alves <pedro@palves.net>2022-12-05 20:44:39 +0000
committerPedro Alves <pedro@palves.net>2023-11-13 14:16:10 +0000
commit7730e5c6c2658658a032a957a78e663350dc5124 (patch)
tree3437b23810e853b676cbc8c5b3dfc01a1ce49858 /gdb/infrun.c
parentad320fbf91e6808699cb69cccca7299a2332074d (diff)
downloadbinutils-7730e5c6c2658658a032a957a78e663350dc5124.zip
binutils-7730e5c6c2658658a032a957a78e663350dc5124.tar.gz
binutils-7730e5c6c2658658a032a957a78e663350dc5124.tar.bz2
Move deleting thread on TARGET_WAITKIND_THREAD_EXITED to core
Currently, infrun assumes that when TARGET_WAITKIND_THREAD_EXITED is reported, the corresponding GDB thread has already been removed from the GDB thread list. Later in the series, that will no longer work, as infrun will need to refer to the thread's thread_info when it processes TARGET_WAITKIND_THREAD_EXITED. As preparation, this patch makes deleting the GDB thread responsibility of infrun, instead of the target. Reviewed-By: Andrew Burgess <aburgess@redhat.com> Change-Id: I013d87f61ffc9aaca49f0d6ce2a43e3ea69274de
Diffstat (limited to 'gdb/infrun.c')
-rw-r--r--gdb/infrun.c32
1 files changed, 27 insertions, 5 deletions
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 03eb32a..e1e761c 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -4352,7 +4352,12 @@ reinstall_readline_callback_handler_cleanup ()
}
/* Clean up the FSMs of threads that are now stopped. In non-stop,
- that's just the event thread. In all-stop, that's all threads. */
+ that's just the event thread. In all-stop, that's all threads. In
+ all-stop, threads that had a pending exit no longer have a reason
+ to be around, as their FSMs/commands are canceled, so we delete
+ them. This avoids "info threads" listing such threads as if they
+ were alive (and failing to read their registers), the user being
+ able to select and resume them (and that failing), etc. */
static void
clean_up_just_stopped_threads_fsms (struct execution_control_state *ecs)
@@ -4370,15 +4375,29 @@ clean_up_just_stopped_threads_fsms (struct execution_control_state *ecs)
{
scoped_restore_current_thread restore_thread;
- for (thread_info *thr : all_non_exited_threads ())
+ for (thread_info *thr : all_threads_safe ())
{
- if (thr->thread_fsm () == nullptr)
+ if (thr->state == THREAD_EXITED)
continue;
+
if (thr == ecs->event_thread)
continue;
- switch_to_thread (thr);
- thr->thread_fsm ()->clean_up (thr);
+ if (thr->thread_fsm () != nullptr)
+ {
+ switch_to_thread (thr);
+ thr->thread_fsm ()->clean_up (thr);
+ }
+
+ /* As we are cancelling the command/FSM of this thread,
+ whatever was the reason we needed to report a thread
+ exited event to the user, that reason is gone. Delete
+ the thread, so that the user doesn't see it in the thread
+ list, the next proceed doesn't try to resume it, etc. */
+ if (thr->has_pending_waitstatus ()
+ && (thr->pending_waitstatus ().kind ()
+ == TARGET_WAITKIND_THREAD_EXITED))
+ delete_thread (thr);
}
}
}
@@ -5728,6 +5747,9 @@ handle_inferior_event (struct execution_control_state *ecs)
if (ecs->ws.kind () == TARGET_WAITKIND_THREAD_EXITED)
{
+ ecs->event_thread = ecs->target->find_thread (ecs->ptid);
+ gdb_assert (ecs->event_thread != nullptr);
+ delete_thread (ecs->event_thread);
prepare_to_wait (ecs);
return;
}