From 3890f02a5b3c3e543619f2493b5dfbbc842559ba Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Mon, 17 Jan 2022 20:49:07 -0500 Subject: [PATCH] gdb/remote: remove_new_fork_children don't access target_waitstatus::child_ptid if kind == TARGET_WAITKIND_THREAD_EXITED Following the previous patch, running gdb.threads/forking-threads-plus-breakpoints.exp continuously eventually gives me an internal error. gdb/target/waitstatus.h:372: internal-error: child_ptid: Assertion `m_kind == TARGET_WAITKIND_FORKED || m_kind == TARGET_WAITKIND_VFORKED' failed.^M FAIL: gdb.threads/forking-threads-plus-breakpoint.exp: cond_bp_target=0: detach_on_fork=on: displaced=off: inferior 1 exited (GDB internal error) The backtrace is: 0x55925b679c85 internal_error(char const*, int, char const*, ...) /home/simark/src/binutils-gdb/gdbsupport/errors.cc:55 0x559258deadd2 target_waitstatus::child_ptid() const /home/simark/src/binutils-gdb/gdb/target/waitstatus.h:372 0x55925a7cbac9 remote_target::remove_new_fork_children(threads_listing_context*) /home/simark/src/binutils-gdb/gdb/remote.c:7311 0x55925a79dfdb remote_target::update_thread_list() /home/simark/src/binutils-gdb/gdb/remote.c:3981 0x55925ad79b83 target_update_thread_list() /home/simark/src/binutils-gdb/gdb/target.c:3793 0x55925addbb15 update_thread_list() /home/simark/src/binutils-gdb/gdb/thread.c:2031 0x559259d64838 stop_all_threads(char const*, inferior*) /home/simark/src/binutils-gdb/gdb/infrun.c:5104 0x559259d88b45 keep_going_pass_signal /home/simark/src/binutils-gdb/gdb/infrun.c:8215 0x559259d8951b keep_going /home/simark/src/binutils-gdb/gdb/infrun.c:8251 0x559259d78835 process_event_stop_test /home/simark/src/binutils-gdb/gdb/infrun.c:6858 0x559259d750e9 handle_signal_stop /home/simark/src/binutils-gdb/gdb/infrun.c:6580 0x559259d6c07b handle_inferior_event /home/simark/src/binutils-gdb/gdb/infrun.c:5832 0x559259d57db8 fetch_inferior_event() /home/simark/src/binutils-gdb/gdb/infrun.c:4222 Indeed, the code accesses target_waitstatus::child_ptid when the kind is TARGET_WAITKIND_THREAD_EXITED, which is not right. A TARGET_WAITKIND_THREAD_EXITED event does not have a child_ptid value associated, it has an exit status, which we are not interested in. The intent is to remove from the thread list the thread that has exited. Its ptid is found in the stop reply event, get it from there. Change-Id: Icb298cbb80b8779fdf0c660dde9a5314d5591535 --- gdb/remote.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gdb/remote.c b/gdb/remote.c index 3f06ba5bb08..122f204fe12 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -7293,9 +7293,10 @@ remote_target::remove_new_fork_children (threads_listing_context *context) remote_notif_get_pending_events (notif); for (auto &event : get_remote_state ()->stop_reply_queue) if (event->ws.kind () == TARGET_WAITKIND_FORKED - || event->ws.kind () == TARGET_WAITKIND_VFORKED - || event->ws.kind () == TARGET_WAITKIND_THREAD_EXITED) + || event->ws.kind () == TARGET_WAITKIND_VFORKED) context->remove_thread (event->ws.child_ptid ()); + else if (event->ws.kind () == TARGET_WAITKIND_THREAD_EXITED) + context->remove_thread (event->ptid); } /* Check whether any event pending in the vStopped queue would prevent a