public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Pedro Alves <palves@redhat.com>
To: gdb-patches@sourceware.org
Subject: [PATCH 3/5] libthread_db: Skip attaching to terminated and joined threads
Date: Tue, 16 Dec 2014 16:54:00 -0000	[thread overview]
Message-ID: <1418748834-27545-4-git-send-email-palves@redhat.com> (raw)
In-Reply-To: <1418748834-27545-1-git-send-email-palves@redhat.com>

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/
2014-12-16  Pedro Alves  <palves@redhat.com>

	* thread-db.c (find_new_threads_callback): Ignore thread if the
	kernel thread ID is -1.

gdb/
2014-12-16  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/gdbserver/thread-db.c | 11 +++++++++++
 gdb/linux-nat.c           |  1 +
 gdb/linux-thread-db.c     | 11 +++++++++++
 3 files changed, 23 insertions(+)

diff --git a/gdb/gdbserver/thread-db.c b/gdb/gdbserver/thread-db.c
index ac94892..2d9980d 100644
--- a/gdb/gdbserver/thread-db.c
+++ b/gdb/gdbserver/thread-db.c
@@ -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;
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index c6b5280..828064f 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -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);
diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c
index a405603..4b26984 100644
--- a/gdb/linux-thread-db.c
+++ b/gdb/linux-thread-db.c
@@ -1606,6 +1606,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
-- 
1.9.3

  parent reply	other threads:[~2014-12-16 16:54 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-12-16 16:54 [PATCH 0/5] GNU/Linux, fix attach races/problems Pedro Alves
2014-12-16 16:54 ` [PATCH 1/5] libthread_db: debug output should go to gdb_stdlog Pedro Alves
2014-12-17  8:02   ` Yao Qi
2014-12-17 13:45     ` Pedro Alves
2014-12-17 14:09       ` Yao Qi
2014-12-16 16:54 ` Pedro Alves [this message]
2014-12-16 16:54 ` [PATCH 4/5] Linux: Skip thread_db thread event reporting if PTRACE_EVENT_CLONE is supported Pedro Alves
2014-12-16 21:24   ` Simon Marchi
2014-12-17 13:04     ` Pedro Alves
2014-12-16 16:54 ` [PATCH 2/5] Linux: on attach, attach to lwps listed under /proc/$pid/task/ Pedro Alves
2014-12-16 20:52   ` Simon Marchi
2014-12-17 13:35     ` Pedro Alves
2014-12-16 17:35 ` [PATCH 5/5] Test attaching to a program that constantly spawns short-lived threads Pedro Alves
2014-12-17 11:10   ` Yao Qi
2014-12-18  0:02     ` Pedro Alves
2015-01-05 19:02       ` Breazeal, Don
2015-01-07 16:17         ` [PATCH] skip "attach" tests when testing against stub-like targets (was: Re: [PATCH 5/5] Test attaching to a program that constantly spawns short-lived threads) Pedro Alves
2015-01-09 11:24           ` [PATCH] skip "attach" tests when testing against stub-like targets Pedro Alves
2015-01-12  4:43             ` [regression/native-gdbserver][buildbot] Python testscases get staled (was: Re: [PATCH] skip "attach" tests when testing against stub-like targets) Sergio Durigan Junior
2015-01-12 11:15               ` [regression/native-gdbserver][buildbot] Python testscases get staled Pedro Alves
2015-01-12 16:55                 ` Sergio Durigan Junior
2015-01-12 17:01                   ` Pedro Alves
2015-01-12 17:13                     ` [PATCH] gdb.python/py-prompt.exp: restore GDBFLAGS Pedro Alves
2015-01-09 12:03 ` [PATCH 0/5] GNU/Linux, fix attach races/problems Pedro Alves

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1418748834-27545-4-git-send-email-palves@redhat.com \
    --to=palves@redhat.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).