aboutsummaryrefslogtreecommitdiff
path: root/gdb/thread-db.c
diff options
context:
space:
mode:
authorDaniel Jacobowitz <drow@false.org>2004-03-29 18:07:14 +0000
committerDaniel Jacobowitz <drow@false.org>2004-03-29 18:07:14 +0000
commita2f23071c92ee8e0ad72cef70e82af6192b48ba9 (patch)
tree42d5acab992069bc32ad50036e985434d3e25e50 /gdb/thread-db.c
parent8d5f9dcb37b90814ac723d46d5b93169da19e391 (diff)
downloadgdb-a2f23071c92ee8e0ad72cef70e82af6192b48ba9.zip
gdb-a2f23071c92ee8e0ad72cef70e82af6192b48ba9.tar.gz
gdb-a2f23071c92ee8e0ad72cef70e82af6192b48ba9.tar.bz2
* Makefile.in (linux_nat_h): Update dependencies.
* configure.in: Check for <gnu/libc-version.h>. * configure: Regenerate. * config.in: Regenerate. * linux-nat.h: Include "target.h". Add waitstatus field to struct lwp_info. * lin-lwp.c (add_lwp): Initialize waitstatus.kind. (lin_lwp_attach_lwp): Don't attach to LWPs we have already attached to. (lin_lwp_handle_extended): New function. Handle clone events. (wait_lwp): Use lin_lwp_handle_extended. Update comment about thread exit events. (child_wait): Handle clone events. (lin_lwp_wait: Use lin_lwp_handle_extended and handle clone events. * linux-nat.c (linux_enable_event_reporting): Turn on PTRACE_O_TRACECLONE. (linux_handle_extended_wait): Handle clone events. * thread-db.c: Include <gnu/libc-version.h>. (struct private_thread_info): Add dying flag. (enable_thread_event_reporting): Enable TD_DEATH for glibc 2.2 and higher. (attach_thread): Update comments. Handle dying threads. (detach_thread): Set the dying flag. (check_event): Always call attach_thread.
Diffstat (limited to 'gdb/thread-db.c')
-rw-r--r--gdb/thread-db.c69
1 files changed, 60 insertions, 9 deletions
diff --git a/gdb/thread-db.c b/gdb/thread-db.c
index 804f48a..4683847 100644
--- a/gdb/thread-db.c
+++ b/gdb/thread-db.c
@@ -1,6 +1,6 @@
/* libthread_db assisted debugging support, generic parts.
- Copyright 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+ Copyright 1999, 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
This file is part of GDB.
@@ -35,6 +35,10 @@
#include "regcache.h"
#include "solib-svr4.h"
+#ifdef HAVE_GNU_LIBC_VERSION_H
+#include <gnu/libc-version.h>
+#endif
+
#ifndef LIBTHREAD_DB_SO
#define LIBTHREAD_DB_SO "libthread_db.so.1"
#endif
@@ -130,6 +134,7 @@ static CORE_ADDR td_death_bp_addr;
static void thread_db_find_new_threads (void);
static void attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
const td_thrinfo_t *ti_p, int verbose);
+static void detach_thread (ptid_t ptid, int verbose);
/* Building process ids. */
@@ -150,6 +155,9 @@ static void attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
struct private_thread_info
{
+ /* Flag set when we see a TD_DEATH event for this thread. */
+ unsigned int dying:1;
+
/* Cached thread state. */
unsigned int th_valid:1;
unsigned int ti_valid:1;
@@ -491,6 +499,10 @@ enable_thread_event_reporting (void)
td_thr_events_t events;
td_notify_t notify;
td_err_e err;
+#ifdef HAVE_GNU_LIBC_VERSION_H
+ const char *libc_version;
+ int libc_major, libc_minor;
+#endif
/* We cannot use the thread event reporting facility if these
functions aren't available. */
@@ -501,12 +513,16 @@ enable_thread_event_reporting (void)
/* Set the process wide mask saying which events we're interested in. */
td_event_emptyset (&events);
td_event_addset (&events, TD_CREATE);
-#if 0
+
+#ifdef HAVE_GNU_LIBC_VERSION_H
/* FIXME: kettenis/2000-04-23: The event reporting facility is
broken for TD_DEATH events in glibc 2.1.3, so don't enable it for
now. */
- td_event_addset (&events, TD_DEATH);
+ libc_version = gnu_get_libc_version ();
+ if (sscanf (libc_version, "%d.%d", &libc_major, &libc_minor) == 2
+ && (libc_major > 2 || (libc_major == 2 && libc_minor > 1)))
#endif
+ td_event_addset (&events, TD_DEATH);
err = td_ta_set_event_p (thread_agent, &events);
if (err != TD_OK)
@@ -689,6 +705,10 @@ quit:
target_new_objfile_chain (objfile);
}
+/* Attach to a new thread. This function is called when we receive a
+ TD_CREATE event or when we iterate over all threads and find one
+ that wasn't already in our list. */
+
static void
attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
const td_thrinfo_t *ti_p, int verbose)
@@ -696,6 +716,27 @@ attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
struct thread_info *tp;
td_err_e err;
+ /* If we're being called after a TD_CREATE event, we may already
+ know about this thread. There are two ways this can happen. We
+ may have iterated over all threads between the thread creation
+ and the TD_CREATE event, for instance when the user has issued
+ the `info threads' command before the SIGTRAP for hitting the
+ thread creation breakpoint was reported. Alternatively, the
+ thread may have exited and a new one been created with the same
+ thread ID. In the first case we don't need to do anything; in
+ the second case we should discard information about the dead
+ thread and attach to the new one. */
+ if (in_thread_list (ptid))
+ {
+ tp = find_thread_pid (ptid);
+ gdb_assert (tp != NULL);
+
+ if (!tp->private->dying)
+ return;
+
+ delete_thread (ptid);
+ }
+
check_thread_signals ();
/* Add the thread to GDB's thread list. */
@@ -741,8 +782,21 @@ thread_db_attach (char *args, int from_tty)
static void
detach_thread (ptid_t ptid, int verbose)
{
+ struct thread_info *thread_info;
+
if (verbose)
printf_unfiltered ("[%s exited]\n", target_pid_to_str (ptid));
+
+ /* Don't delete the thread now, because it still reports as active
+ until it has executed a few instructions after the event
+ breakpoint - if we deleted it now, "info threads" would cause us
+ to re-attach to it. Just mark it as having had a TD_DEATH
+ event. This means that we won't delete it from our thread list
+ until we notice that it's dead (via prune_threads), or until
+ something re-uses its thread ID. */
+ thread_info = find_thread_pid (ptid);
+ gdb_assert (thread_info != NULL);
+ thread_info->private->dying = 1;
}
static void
@@ -847,12 +901,9 @@ check_event (ptid_t ptid)
switch (msg.event)
{
case TD_CREATE:
-
- /* We may already know about this thread, for instance when the
- user has issued the `info threads' command before the SIGTRAP
- for hitting the thread creation breakpoint was reported. */
- if (!in_thread_list (ptid))
- attach_thread (ptid, msg.th_p, &ti, 1);
+ /* Call attach_thread whether or not we already know about a
+ thread with this thread ID. */
+ attach_thread (ptid, msg.th_p, &ti, 1);
break;