aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2017-09-29 13:06:34 +0100
committerPedro Alves <palves@redhat.com>2017-09-29 13:06:34 +0100
commit94c207e097a3a30ce71fc8f700325113968c276b (patch)
treedb4cc65cb31bde9bcfbdac32c6ab0be00d540b3e
parentf6ac8c52c955b487dcb56d05fc93fced7b203294 (diff)
downloadgdb-94c207e097a3a30ce71fc8f700325113968c276b.zip
gdb-94c207e097a3a30ce71fc8f700325113968c276b.tar.gz
gdb-94c207e097a3a30ce71fc8f700325113968c276b.tar.bz2
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.
-rw-r--r--gdb/gdbserver/ChangeLog10
-rw-r--r--gdb/gdbserver/linux-low.c2
-rw-r--r--gdb/gdbserver/linux-low.h2
-rw-r--r--gdb/gdbserver/thread-db.c17
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");
}