This is the mail archive of the gdb-cvs@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] Fix gdbserver regression exposed by gdb.threads/multi-create-ns-info-thr.exp


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=94c207e097a3a30ce71fc8f700325113968c276b

commit 94c207e097a3a30ce71fc8f700325113968c276b
Author: Pedro Alves <palves@redhat.com>
Date:   Fri Sep 29 13:06:34 2017 +0100

    Fix gdbserver regression exposed by gdb.threads/multi-create-ns-info-thr.exp
    
    Commit 8629910955a7 ("Add thread_db_notice_clone to gdbserver")
    introduced calls into libthread_db without making sure that the
    current thread is pointing to a know-stopped thread.  This resulted in
    sometimes thread_db_notice_clone failing->find_one_thread failing like
    this, as seen when running gdb.threads/multi-create-ns-info-thr.exp:
    
    ~~~
      Thread <6> executing
      Thread <7> executing
      gdbserver: PID mismatch!  Expected 27472, got 27471
      gdbserver: Cannot find thread after clone.
    
      Thread <1000> executing
      Thread <1001> executing
    ~~~
    
    Things go south from here and sometimes that ends up resulting in
    gdbserver crashing and the test failing.
    
    gdb/gdbserver/ChangeLog:
    2017-09-29  Pedro Alves  <palves@redhat.com>
    
    	* linux-low.c (handle_extended_wait): Pass parent thread instead
    	of process to thread_db_notice_clone.
    	* linux-low.h (thread_db_notice_clone): Replace parent process
    	parameter with parent thread parameter.
    	* thread-db.c (find_one_thread): Add comment.
    	(thread_db_notice_clone): Replace parent process parameter with
    	parent thread parameter.  Temporarily switch to the parent thread.

Diff:
---
 gdb/gdbserver/ChangeLog   | 10 ++++++++++
 gdb/gdbserver/linux-low.c |  2 +-
 gdb/gdbserver/linux-low.h |  2 +-
 gdb/gdbserver/thread-db.c | 17 ++++++++++++++---
 4 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 63fb653..f27451d 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,13 @@
+2017-09-29  Pedro Alves  <palves@redhat.com>
+
+	* linux-low.c (handle_extended_wait): Pass parent thread instead
+	of process to thread_db_notice_clone.
+	* linux-low.h (thread_db_notice_clone): Replace parent process
+	parameter with parent thread parameter.
+	* thread-db.c (find_one_thread): Add comment.
+	(thread_db_notice_clone): Replace parent process parameter with
+	parent thread parameter.  Temporarily switch to the parent thread.
+
 2017-09-26  Sergio Durigan Junior  <sergiodj@redhat.com>
 
 	* gdbthread.h: Include "common-gdbthread.h".
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index c62dc19..54005c1 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -656,7 +656,7 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
 	  new_lwp->status_pending = status;
 	}
 
-      thread_db_notice_clone (get_thread_process (event_thr), ptid);
+      thread_db_notice_clone (event_thr, ptid);
 
       /* Don't report the event.  */
       return 1;
diff --git a/gdb/gdbserver/linux-low.h b/gdb/gdbserver/linux-low.h
index 85bb8ca..0ece7bc 100644
--- a/gdb/gdbserver/linux-low.h
+++ b/gdb/gdbserver/linux-low.h
@@ -417,7 +417,7 @@ int thread_db_look_up_one_symbol (const char *name, CORE_ADDR *addrp);
    both the clone and the parent should be stopped.  This function does
    whatever is required have the clone under thread_db's control.  */
 
-void thread_db_notice_clone (struct process_info *proc, ptid_t lwp);
+void thread_db_notice_clone (struct thread_info *parent_thr, ptid_t child_ptid);
 
 bool thread_db_thread_handle (ptid_t ptid, gdb_byte **handle, int *handle_len);
 
diff --git a/gdb/gdbserver/thread-db.c b/gdb/gdbserver/thread-db.c
index 9156d89..638a833 100644
--- a/gdb/gdbserver/thread-db.c
+++ b/gdb/gdbserver/thread-db.c
@@ -28,6 +28,7 @@ extern int debug_threads;
 #include "nat/gdb_thread_db.h"
 #include "gdb_vecs.h"
 #include "nat/linux-procfs.h"
+#include "common/scoped_restore.h"
 
 #ifndef USE_LIBTHREAD_DB_DIRECTLY
 #include <dlfcn.h>
@@ -155,6 +156,9 @@ thread_db_state_str (td_thr_state_e state)
 }
 #endif
 
+/* Get thread info about PTID, accessing memory via the current
+   thread.  */
+
 static int
 find_one_thread (ptid_t ptid)
 {
@@ -887,15 +891,22 @@ thread_db_handle_monitor_command (char *mon)
 /* See linux-low.h.  */
 
 void
-thread_db_notice_clone (struct process_info *proc, ptid_t ptid)
+thread_db_notice_clone (struct thread_info *parent_thr, ptid_t child_ptid)
 {
-  struct thread_db *thread_db = proc->priv->thread_db;
+  process_info *parent_proc = get_thread_process (parent_thr);
+  struct thread_db *thread_db = parent_proc->priv->thread_db;
 
   /* If the thread layer isn't initialized, return.  It may just
      be that the program uses clone, but does not use libthread_db.  */
   if (thread_db == NULL || !thread_db->all_symbols_looked_up)
     return;
 
-  if (!find_one_thread (ptid))
+  /* find_one_thread calls into libthread_db which accesses memory via
+     the current thread.  Temporarily switch to a thread we know is
+     stopped.  */
+  scoped_restore restore_current_thread
+    = make_scoped_restore (&current_thread, parent_thr);
+
+  if (!find_one_thread (child_ptid))
     warning ("Cannot find thread after clone.\n");
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]