Fix gdbserver regression exposed by gdb.threads/multi-create-ns-info-thr.exp
Commit 8629910955
("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.
This commit is contained in:
parent
f6ac8c52c9
commit
94c207e097
@ -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".
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 (¤t_thread, parent_thr);
|
||||
|
||||
if (!find_one_thread (child_ptid))
|
||||
warning ("Cannot find thread after clone.\n");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user