PR remote/19496, internal err forking-threads-plus-bkpt
authorDon Breazeal <donb@codesourcery.com>
Tue, 16 Feb 2016 16:56:06 +0000 (08:56 -0800)
committerDon Breazeal <donb@codesourcery.com>
Tue, 16 Feb 2016 16:56:06 +0000 (08:56 -0800)
This patch fixes an internal error that occurs in
gdb.threads/forking-threads-plus-breakpoint.exp:

/blah/binutils-gdb/gdb/target.c:2723: internal-error: Can't determine the
current address space of thread Thread 3170.3170

In default_thread_address_space, find_inferior_ptid couldn't find 3170.3170
because it had been overwritten in inferior_appeared, called as follows:

inferior_appeared
  remote_add_inferior
    remote_notice_new_inferior
      remote_update_thread_list

The cause of the problem was the following sequence of events:

* GDB knows only about the main thread

* the first fork event is reported to GDB, saved as pending_event

* qXfer:threads:read gets the threads from the remote.
  remove_new_fork_children id's the fork child from the pending event
  and removes it from the list reported to GDB.  All the rest of the
  threads, including the fork parent, are added to the GDB thread list.

* GDB stops all the threads.  All the stop events are pushed onto the
  stop reply queue behind the pending fork event.  The fork waitstatus
  is saved in the fork parent thread's pending status field
  thread_info.suspend.

* remote_wait_ns calls queued_stop_reply and process_stop_reply to
  remove the fork event from the front of the stop reply queue and save
  event information in the thread_info structure for the fork parent
  thread.  Unfortunately, none of the information saved in this way is
  the fork-specific information.

* A subsequent qXfer:threads:read packet gets the thread list including
  the fork parent and fork child.  remove_new_fork_children checks the
  thread list to see if there is a fork parent, doesn't find one, checks
  the stop reply queue for a pending fork event, doesn't find one, and
  allows the fork child thread to be reported to GDB before the fork
  event has been handled.  remote_update_thread_list calls
  remote_notice_new_thread and overwrites the current (main) thread in
  inferior_appeared.

So the fork event has been reported out of target_wait but it was left
pending on the infrun side (infrun.c:save_waitstatus).  IOW, the fork
event hasn't been processed by handle_inferior_event yet, so it hasn't
made it to tp->pending_follow yet.

The fix is to check thread_info.suspend along with the
thread_info.pending_follow in remote.c:remove_new_fork_children, to
prevent premature reporting of the fork child thread creation.

gdb/ChangeLog:

PR remote/19496
* remote.c (remove_new_fork_children): Check for pending
fork status in thread_info.suspend.

gdb/testsuite/ChangeLog:

PR remote/19496
* gdb.threads/forking-threads-plus-breakpoint.exp (do_test):
Remove kfail for PR remote/19496.

gdb/ChangeLog
gdb/remote.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.threads/forking-threads-plus-breakpoint.exp

index 5b743c4ac93904858075699f58473b77eece408e..327ce7bf87941473b1b493c6e238bf0453b07775 100644 (file)
@@ -1,3 +1,9 @@
+2016-02-16  Don Breazeal  <donb@codesourcery.com>
+
+       PR remote/19496
+       * remote.c (remove_new_fork_children): Check for pending
+       fork status in thread_info.suspend.
+
 2016-02-16  Yao Qi  <yao.qi@linaro.org>
 
        * arm-linux-tdep.c (arm_linux_software_single_step): Assign
index 6d56f1908d69c203c614d467e2f4d86d2e261b8b..f09a06e9dcc283426dd63e6917d825cbabd6b694 100644 (file)
@@ -6166,7 +6166,12 @@ remove_new_fork_children (struct threads_listing_context *context)
      fork child threads from the CONTEXT list.  */
   ALL_NON_EXITED_THREADS (thread)
     {
-      struct target_waitstatus *ws = &thread->pending_follow;
+      struct target_waitstatus *ws;
+
+      if (thread->suspend.waitstatus_pending_p)
+       ws = &thread->suspend.waitstatus;
+      else
+       ws = &thread->pending_follow;
 
       if (is_pending_fork_parent (ws, pid, thread->ptid))
        {
index fa4eecf5180a8d66ef5b058fc78ef9a0e48c81f5..37b158790af416f19bf57c41252e540c519c9c9a 100644 (file)
@@ -1,3 +1,9 @@
+2016-02-16  Don Breazeal  <donb@codesourcery.com>
+
+       PR remote/19496
+       * gdb.threads/forking-threads-plus-breakpoint.exp (do_test):
+       Remove kfail for PR remote/19496.
+
 2016-02-16  Simon Marchi  <simon.marchi@ericsson.com>
 
        * lib/gdb.exp (standard_temp_file): Return a path specific to
index 6c7206126b7501e36413f31e2fc814212ac07344..ff3ca9af59cf604253b1b4d35ce1f434c4e06036 100644 (file)
@@ -100,12 +100,6 @@ proc do_test { cond_bp_target detach_on_fork displaced } {
     set fork_count 0
     set ok 0
 
-    if {$displaced == "off"
-       && [target_info exists gdb_protocol]
-       && ([target_info gdb_protocol] == "remote"
-           || [target_info gdb_protocol] == "extended-remote")} {
-       setup_kfail "remote/19496" *-*-*
-    }
     set test "inferior 1 exited"
     gdb_test_multiple "" $test {
        -re "Inferior 1 \(\[^\r\n\]+\) exited normally" {