gdb/remote: remove_new_fork_children don't access target_waitstatus::child_ptid if...
authorSimon Marchi <simon.marchi@polymtl.ca>
Tue, 18 Jan 2022 01:49:07 +0000 (20:49 -0500)
committerSimon Marchi <simon.marchi@polymtl.ca>
Tue, 5 Apr 2022 02:11:56 +0000 (22:11 -0400)
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

index 3f06ba5bb08cc50b1ac8be80c9370f35d5ce19c8..122f204fe12b4c6c3f24a74e8108fdfb3930988b 100644 (file)
@@ -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