diff options
author | Pedro Alves <palves@redhat.com> | 2015-12-17 14:20:52 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2015-12-17 14:23:28 +0000 |
commit | a6904d5a6aa63e4bef7207407250d8b76b56f8a9 (patch) | |
tree | e4651001446dda94d8b8f04382b7b916028cb5ff /gdb/linux-thread-db.c | |
parent | 4a6ed09b0f70c79b11bc1e0973a7333d9316a287 (diff) | |
download | gdb-a6904d5a6aa63e4bef7207407250d8b76b56f8a9.zip gdb-a6904d5a6aa63e4bef7207407250d8b76b56f8a9.tar.gz gdb-a6904d5a6aa63e4bef7207407250d8b76b56f8a9.tar.bz2 |
Fix PR threads/19354: "info threads" error with multiple inferiors
Note: this applies on top of:
[PATCH] Remove support for LinuxThreads and vendor 2.4 kernels w/ backported NPTL
https://sourceware.org/ml/gdb-patches/2015-12/msg00214.html
We try to avoid using libthread_db.so to list threads in the inferior
when debugging live processes, but the code that decides whether to
use it decides incorrectly if you have more than one inferior, and the
current inferior doesn't have execution yet. The result is visible
as:
(gdb) add-inferior
Added inferior 2
(gdb) inferior 2
[Switching to inferior 2 [<null>] (<noexec>)]
(gdb) info inferiors
Num Description Executable
1 process 15397 /home/pedro/gdb/tests/threads
* 2 <null>
(gdb) info threads
Cannot find new threads: generic error
(gdb)
Fix this by checking whether each inferior has execution rather than
just the current inferior.
By moving the core updating to linux-nat.c's update_thread_list
implementation, this also ends up fixing the
lwp-last-seen-running-on-core updating in the case we're debugging a
program that uses raw clone rather than pthreads, as linux-thread-db.c
isn't pushed in the target stack in that scenario.
Tested on x86_64 Fedora 20.
gdb/ChangeLog:
2015-12-17 Pedro Alves <palves@redhat.com>
PR threads/19354
* linux-nat.c (linux_nat_update_thread_list): Update process cores
each lwp was last seen running on here.
* linux-thread-db.c (update_thread_core): Delete.
(thread_db_update_thread_list_td_ta_thr_iter): Rename to ...
(thread_db_update_thread_list): ... this. Skip inferiors with
execution. Also call the target beneath.
(thread_db_update_thread_list): Delete.
gdb/testsuite/ChangeLog:
2015-12-17 Pedro Alves <palves@redhat.com>
PR threads/19354
* gdb.multi/info-threads.exp: New file.
Diffstat (limited to 'gdb/linux-thread-db.c')
-rw-r--r-- | gdb/linux-thread-db.c | 53 |
1 files changed, 19 insertions, 34 deletions
diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c index ce3f6a1..68b6988 100644 --- a/gdb/linux-thread-db.c +++ b/gdb/linux-thread-db.c @@ -1324,17 +1324,11 @@ thread_db_find_new_threads_1 (ptid_t ptid) thread_db_find_new_threads_2 (ptid, 0); } -static int -update_thread_core (struct lwp_info *info, void *closure) -{ - info->core = linux_common_core_of_thread (info->ptid); - return 0; -} - -/* Update the thread list using td_ta_thr_iter. */ +/* Implement the to_update_thread_list target method for this + target. */ static void -thread_db_update_thread_list_td_ta_thr_iter (struct target_ops *ops) +thread_db_update_thread_list (struct target_ops *ops) { struct thread_db_info *info; struct inferior *inf; @@ -1356,34 +1350,25 @@ thread_db_update_thread_list_td_ta_thr_iter (struct target_ops *ops) if (thread == NULL || thread->executing) continue; + /* It's best to avoid td_ta_thr_iter if possible. That walks + data structures in the inferior's address space that may be + corrupted, or, if the target is running, the list may change + while we walk it. In the latter case, it's possible that a + thread exits just at the exact time that causes GDB to get + stuck in an infinite loop. To avoid pausing all threads + whenever the core wants to refresh the thread list, we + instead use thread_from_lwp immediately when we see an LWP + stop. That uses thread_db entry points that do not walk + libpthread's thread list, so should be safe, as well as more + efficient. */ + if (target_has_execution_1 (thread->ptid)) + continue; + thread_db_find_new_threads_1 (thread->ptid); } -} -/* Implement the to_update_thread_list target method for this - target. */ - -static void -thread_db_update_thread_list (struct target_ops *ops) -{ - /* It's best to avoid td_ta_thr_iter if possible. That walks data - structures in the inferior's address space that may be corrupted, - or, if the target is running, the list may change while we walk - it. In the latter case, it's possible that a thread exits just - at the exact time that causes GDB to get stuck in an infinite - loop. To avoid pausing all threads whenever the core wants to - refresh the thread list, use thread_from_lwp immediately when we - see an LWP stop. That uses thread_db entry points that do not - walk libpthread's thread list, so should be safe, as well as - more efficient. */ - if (target_has_execution) - ops->beneath->to_update_thread_list (ops->beneath); - else - thread_db_update_thread_list_td_ta_thr_iter (ops); - - if (target_has_execution) - iterate_over_lwps (minus_one_ptid /* iterate over all */, - update_thread_core, NULL); + /* Give the beneath target a chance to do extra processing. */ + ops->beneath->to_update_thread_list (ops->beneath); } static char * |