libthread_db: Skip attaching to terminated and joined threads
authorPedro Alves <palves@redhat.com>
Tue, 16 Dec 2014 16:12:24 +0000 (16:12 +0000)
committerPedro Alves <palves@redhat.com>
Fri, 9 Jan 2015 11:41:01 +0000 (11:41 +0000)
commita33e39599ce39ec6225d71f7da1719b544740745
tree6ae0a75c900c6f95e33ff3285b3912cd512863da
parent8784d56326e72e2e6863e8443b1f97e45a46ba36
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.
gdb/ChangeLog
gdb/gdbserver/ChangeLog
gdb/gdbserver/thread-db.c
gdb/linux-nat.c
gdb/linux-thread-db.c