libthread_db: Skip attaching to terminated and joined threads
I wrote a test that attaches to a program that constantly spawns short-lived threads, which exposed several issues. This is one of them. On GNU/Linux, attaching to a multi-threaded program sometimes prints out warnings like: ... [New LWP 20700] warning: unable to open /proc file '/proc/-1/status' [New LWP 20850] [New LWP 21019] ... That happens because when a thread exits, and is joined, glibc does: nptl/pthread_join.c: pthread_join () { ... if (__glibc_likely (result == 0)) { /* We mark the thread as terminated and as joined. */ pd->tid = -1; ... /* Free the TCB. */ __free_tcb (pd); } So if we attach or interrupt the program (which does an implicit "info threads") at just the right (or rather, wrong) time, we can find and return threads in the libthread_db/pthreads thread list with kernel thread ID -1. I've filed glibc PR nptl/17707 for this. You'll find more info there. This patch handles this as a special case in GDB. This is actually more than just a cosmetic issue. lin_lwp_attach_lwp will think that this -1 is an LWP we're not attached to yet, and after failing to attach will try to check we were already attached to the process, using a waitpid call, which in this case ends up being "waitpid (-1, ...", which obviously results in GDB potentially discarding an event when it shouldn't... Tested on x86_64 Fedora 20, native and gdbserver. gdb/gdbserver/ 2015-01-09 Pedro Alves <palves@redhat.com> * thread-db.c (find_new_threads_callback): Ignore thread if the kernel thread ID is -1. gdb/ 2015-01-09 Pedro Alves <palves@redhat.com> * linux-nat.c (lin_lwp_attach_lwp): Assert that the lwp id we're about to wait for is > 0. * linux-thread-db.c (find_new_threads_callback): Ignore thread if the kernel thread ID is -1.
This commit is contained in:
parent
8784d56326
commit
a33e39599c
5 changed files with 35 additions and 0 deletions
|
@ -1,3 +1,10 @@
|
|||
2015-01-09 Pedro Alves <palves@redhat.com>
|
||||
|
||||
* linux-nat.c (lin_lwp_attach_lwp): Assert that the lwp id we're
|
||||
about to wait for is > 0.
|
||||
* linux-thread-db.c (find_new_threads_callback): Ignore thread if
|
||||
the kernel thread ID is -1.
|
||||
|
||||
2015-01-09 Pedro Alves <palves@redhat.com>
|
||||
|
||||
* linux-nat.c (attach_proc_task_lwp_callback): New function.
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2015-01-09 Pedro Alves <palves@redhat.com>
|
||||
|
||||
* thread-db.c (find_new_threads_callback): Ignore thread if the
|
||||
kernel thread ID is -1.
|
||||
|
||||
2015-01-09 Pedro Alves <palves@redhat.com>
|
||||
|
||||
* linux-low.c (linux_attach_fail_reason_string): Move to
|
||||
|
|
|
@ -396,6 +396,17 @@ find_new_threads_callback (const td_thrhandle_t *th_p, void *data)
|
|||
if (err != TD_OK)
|
||||
error ("Cannot get thread info: %s", thread_db_err_str (err));
|
||||
|
||||
if (ti.ti_lid == -1)
|
||||
{
|
||||
/* A thread with kernel thread ID -1 is either a thread that
|
||||
exited and was joined, or a thread that is being created but
|
||||
hasn't started yet, and that is reusing the tcb/stack of a
|
||||
thread that previously exited and was joined. (glibc marks
|
||||
terminated and joined threads with kernel thread ID -1. See
|
||||
glibc PR17707. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check for zombies. */
|
||||
if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE)
|
||||
return 0;
|
||||
|
|
|
@ -1023,6 +1023,7 @@ lin_lwp_attach_lwp (ptid_t ptid)
|
|||
|
||||
/* See if we've got a stop for this new child
|
||||
pending. If so, we're already attached. */
|
||||
gdb_assert (lwpid > 0);
|
||||
new_pid = my_waitpid (lwpid, &status, WNOHANG);
|
||||
if (new_pid == -1 && errno == ECHILD)
|
||||
new_pid = my_waitpid (lwpid, &status, __WCLONE | WNOHANG);
|
||||
|
|
|
@ -1610,6 +1610,17 @@ find_new_threads_callback (const td_thrhandle_t *th_p, void *data)
|
|||
error (_("find_new_threads_callback: cannot get thread info: %s"),
|
||||
thread_db_err_str (err));
|
||||
|
||||
if (ti.ti_lid == -1)
|
||||
{
|
||||
/* A thread with kernel thread ID -1 is either a thread that
|
||||
exited and was joined, or a thread that is being created but
|
||||
hasn't started yet, and that is reusing the tcb/stack of a
|
||||
thread that previously exited and was joined. (glibc marks
|
||||
terminated and joined threads with kernel thread ID -1. See
|
||||
glibc PR17707. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ti.ti_tid == 0)
|
||||
{
|
||||
/* A thread ID of zero means that this is the main thread, but
|
||||
|
|
Loading…
Reference in a new issue