mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-23 18:14:13 +08:00
* 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.
This commit is contained in:
parent
8d5f9dcb37
commit
a2f23071c9
@ -1,3 +1,30 @@
|
||||
2004-03-29 Daniel Jacobowitz <drow@mvista.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2004-03-29 Daniel Jacobowitz <drow@mvista.com>
|
||||
|
||||
* mips-tdep.c (mips_pdr_data): New.
|
||||
|
@ -699,7 +699,7 @@ kod_h = kod.h
|
||||
language_h = language.h
|
||||
libunwind_frame_h = libunwind-frame.h $(libunwind_h)
|
||||
linespec_h = linespec.h
|
||||
linux_nat_h = linux-nat.h
|
||||
linux_nat_h = linux-nat.h $(target_h)
|
||||
m2_lang_h = m2-lang.h
|
||||
m68k_tdep_h = m68k-tdep.h
|
||||
macroexp_h = macroexp.h
|
||||
|
@ -266,6 +266,9 @@
|
||||
/* Define if you have the <dirent.h> header file. */
|
||||
#undef HAVE_DIRENT_H
|
||||
|
||||
/* Define if you have the <gnu/libc-version.h> header file. */
|
||||
#undef HAVE_GNU_LIBC_VERSION_H
|
||||
|
||||
/* Define if you have the <libunwind-ia64.h> header file. */
|
||||
#undef HAVE_LIBUNWIND_IA64_H
|
||||
|
||||
|
2
gdb/configure
vendored
2
gdb/configure
vendored
@ -4756,7 +4756,7 @@ else
|
||||
fi
|
||||
done
|
||||
|
||||
for ac_hdr in proc_service.h thread_db.h
|
||||
for ac_hdr in proc_service.h thread_db.h gnu/libc-version.h
|
||||
do
|
||||
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
|
||||
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
|
||||
|
@ -342,7 +342,7 @@ AC_CHECK_HEADERS(link.h)
|
||||
AC_CHECK_HEADERS(machine/reg.h)
|
||||
AC_CHECK_HEADERS(nlist.h)
|
||||
AC_CHECK_HEADERS(poll.h sys/poll.h)
|
||||
AC_CHECK_HEADERS(proc_service.h thread_db.h)
|
||||
AC_CHECK_HEADERS(proc_service.h thread_db.h gnu/libc-version.h)
|
||||
AC_CHECK_HEADERS(stddef.h)
|
||||
AC_CHECK_HEADERS(stdlib.h)
|
||||
AC_CHECK_HEADERS(stdint.h)
|
||||
|
123
gdb/lin-lwp.c
123
gdb/lin-lwp.c
@ -1,5 +1,5 @@
|
||||
/* Multi-threaded debugging support for GNU/Linux (LWP layer).
|
||||
Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
||||
Copyright 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
@ -183,6 +183,8 @@ add_lwp (ptid_t ptid)
|
||||
|
||||
memset (lp, 0, sizeof (struct lwp_info));
|
||||
|
||||
lp->waitstatus.kind = TARGET_WAITKIND_IGNORE;
|
||||
|
||||
lp->ptid = ptid;
|
||||
|
||||
lp->next = lwp_list;
|
||||
@ -278,7 +280,7 @@ lin_lwp_open (char *args, int from_tty)
|
||||
void
|
||||
lin_lwp_attach_lwp (ptid_t ptid, int verbose)
|
||||
{
|
||||
struct lwp_info *lp;
|
||||
struct lwp_info *lp, *found_lp;
|
||||
|
||||
gdb_assert (is_lwp (ptid));
|
||||
|
||||
@ -293,13 +295,17 @@ lin_lwp_attach_lwp (ptid_t ptid, int verbose)
|
||||
if (verbose)
|
||||
printf_filtered ("[New %s]\n", target_pid_to_str (ptid));
|
||||
|
||||
lp = find_lwp_pid (ptid);
|
||||
found_lp = lp = find_lwp_pid (ptid);
|
||||
if (lp == NULL)
|
||||
lp = add_lwp (ptid);
|
||||
|
||||
/* We assume that we're already attached to any LWP that has an
|
||||
id equal to the overall process id. */
|
||||
if (GET_LWP (ptid) != GET_PID (ptid))
|
||||
/* We assume that we're already attached to any LWP that has an id
|
||||
equal to the overall process id, and to any LWP that is already
|
||||
in our list of LWPs. If we're not seeing exit events from threads
|
||||
and we've had PID wraparound since we last tried to stop all threads,
|
||||
this assumption might be wrong; fortunately, this is very unlikely
|
||||
to happen. */
|
||||
if (GET_LWP (ptid) != GET_PID (ptid) && found_lp == NULL)
|
||||
{
|
||||
pid_t pid;
|
||||
int status;
|
||||
@ -590,6 +596,41 @@ kill_lwp (int lwpid, int signo)
|
||||
return kill (lwpid, signo);
|
||||
}
|
||||
|
||||
/* Handle a GNU/Linux extended wait response. Most of the work we
|
||||
just pass off to linux_handle_extended_wait, but if it reports a
|
||||
clone event we need to add the new LWP to our list (and not report
|
||||
the trap to higher layers). This function returns non-zero if
|
||||
the event should be ignored and we should wait again. */
|
||||
|
||||
static int
|
||||
lin_lwp_handle_extended (struct lwp_info *lp, int status)
|
||||
{
|
||||
linux_handle_extended_wait (GET_LWP (lp->ptid), status,
|
||||
&lp->waitstatus);
|
||||
|
||||
/* TARGET_WAITKIND_SPURIOUS is used to indicate clone events. */
|
||||
if (lp->waitstatus.kind == TARGET_WAITKIND_SPURIOUS)
|
||||
{
|
||||
struct lwp_info *new_lp;
|
||||
new_lp = add_lwp (BUILD_LWP (lp->waitstatus.value.related_pid,
|
||||
GET_PID (inferior_ptid)));
|
||||
new_lp->cloned = 1;
|
||||
new_lp->stopped = 1;
|
||||
|
||||
lp->waitstatus.kind = TARGET_WAITKIND_IGNORE;
|
||||
|
||||
if (debug_lin_lwp)
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
"LLHE: Got clone event from LWP %ld, resuming\n",
|
||||
GET_LWP (lp->ptid));
|
||||
ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Wait for LP to stop. Returns the wait status, or 0 if the LWP has
|
||||
exited. */
|
||||
|
||||
@ -609,9 +650,11 @@ wait_lwp (struct lwp_info *lp)
|
||||
pid = waitpid (GET_LWP (lp->ptid), &status, __WCLONE);
|
||||
if (pid == -1 && errno == ECHILD)
|
||||
{
|
||||
/* The thread has previously exited. We need to delete it now
|
||||
because in the case of NPTL threads, there won't be an
|
||||
exit event unless it is the main thread. */
|
||||
/* The thread has previously exited. We need to delete it
|
||||
now because, for some vendor 2.4 kernels with NPTL
|
||||
support backported, there won't be an exit event unless
|
||||
it is the main thread. 2.6 kernels will report an exit
|
||||
event for each thread that exits, as expected. */
|
||||
thread_dead = 1;
|
||||
if (debug_lin_lwp)
|
||||
fprintf_unfiltered (gdb_stdlog, "WL: %s vanished.\n",
|
||||
@ -658,6 +701,17 @@ wait_lwp (struct lwp_info *lp)
|
||||
|
||||
gdb_assert (WIFSTOPPED (status));
|
||||
|
||||
/* Handle GNU/Linux's extended waitstatus for trace events. */
|
||||
if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP && status >> 16 != 0)
|
||||
{
|
||||
if (debug_lin_lwp)
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
"WL: Handling extended status 0x%06x\n",
|
||||
status);
|
||||
if (lin_lwp_handle_extended (lp, status))
|
||||
return wait_lwp (lp);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -1097,6 +1151,8 @@ child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
|
||||
int status;
|
||||
pid_t pid;
|
||||
|
||||
ourstatus->kind = TARGET_WAITKIND_IGNORE;
|
||||
|
||||
do
|
||||
{
|
||||
set_sigint_trap (); /* Causes SIGINT to be passed on to the
|
||||
@ -1143,6 +1199,25 @@ child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
|
||||
save_errno = EINTR;
|
||||
}
|
||||
|
||||
/* Handle GNU/Linux's extended waitstatus for trace events. */
|
||||
if (pid != -1 && WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP
|
||||
&& status >> 16 != 0)
|
||||
{
|
||||
linux_handle_extended_wait (pid, status, ourstatus);
|
||||
|
||||
/* If we see a clone event, detach the child, and don't
|
||||
report the event. It would be nice to offer some way to
|
||||
switch into a non-thread-db based threaded mode at this
|
||||
point. */
|
||||
if (ourstatus->kind == TARGET_WAITKIND_SPURIOUS)
|
||||
{
|
||||
ptrace (PTRACE_DETACH, ourstatus->value.related_pid, 0, 0);
|
||||
ourstatus->kind = TARGET_WAITKIND_IGNORE;
|
||||
pid = -1;
|
||||
save_errno = EINTR;
|
||||
}
|
||||
}
|
||||
|
||||
clear_sigio_trap ();
|
||||
clear_sigint_trap ();
|
||||
}
|
||||
@ -1159,11 +1234,9 @@ child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
|
||||
return minus_one_ptid;
|
||||
}
|
||||
|
||||
/* Handle GNU/Linux's extended waitstatus for trace events. */
|
||||
if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP && status >> 16 != 0)
|
||||
return linux_handle_extended_wait (pid, status, ourstatus);
|
||||
if (ourstatus->kind == TARGET_WAITKIND_IGNORE)
|
||||
store_waitstatus (ourstatus, status);
|
||||
|
||||
store_waitstatus (ourstatus, status);
|
||||
return pid_to_ptid (pid);
|
||||
}
|
||||
|
||||
@ -1371,6 +1444,20 @@ retry:
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle GNU/Linux's extended waitstatus for trace events. */
|
||||
if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP && status >> 16 != 0)
|
||||
{
|
||||
if (debug_lin_lwp)
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
"LLW: Handling extended status 0x%06x\n",
|
||||
status);
|
||||
if (lin_lwp_handle_extended (lp, status))
|
||||
{
|
||||
status = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if the thread has exited. */
|
||||
if ((WIFEXITED (status) || WIFSIGNALED (status)) && num_lwps > 1)
|
||||
{
|
||||
@ -1588,14 +1675,14 @@ retry:
|
||||
else
|
||||
trap_ptid = null_ptid;
|
||||
|
||||
/* Handle GNU/Linux's extended waitstatus for trace events. */
|
||||
if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP && status >> 16 != 0)
|
||||
if (lp->waitstatus.kind != TARGET_WAITKIND_IGNORE)
|
||||
{
|
||||
linux_handle_extended_wait (GET_LWP (lp->ptid), status, ourstatus);
|
||||
return trap_ptid;
|
||||
*ourstatus = lp->waitstatus;
|
||||
lp->waitstatus.kind = TARGET_WAITKIND_IGNORE;
|
||||
}
|
||||
else
|
||||
store_waitstatus (ourstatus, status);
|
||||
|
||||
store_waitstatus (ourstatus, status);
|
||||
return (threaded ? lp->ptid : pid_to_ptid (GET_LWP (lp->ptid)));
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* GNU/Linux native-dependent code common to multiple platforms.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
@ -224,7 +224,8 @@ linux_enable_event_reporting (ptid_t ptid)
|
||||
if (! linux_supports_tracefork ())
|
||||
return;
|
||||
|
||||
options = PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACEEXEC;
|
||||
options = PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACEEXEC
|
||||
| PTRACE_O_TRACECLONE;
|
||||
if (linux_supports_tracevforkdone ())
|
||||
options |= PTRACE_O_TRACEVFORKDONE;
|
||||
|
||||
@ -391,11 +392,8 @@ linux_handle_extended_wait (int pid, int status,
|
||||
{
|
||||
int event = status >> 16;
|
||||
|
||||
if (event == PTRACE_EVENT_CLONE)
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"unexpected clone event");
|
||||
|
||||
if (event == PTRACE_EVENT_FORK || event == PTRACE_EVENT_VFORK)
|
||||
if (event == PTRACE_EVENT_FORK || event == PTRACE_EVENT_VFORK
|
||||
|| event == PTRACE_EVENT_CLONE)
|
||||
{
|
||||
unsigned long new_pid;
|
||||
int ret;
|
||||
@ -406,12 +404,10 @@ linux_handle_extended_wait (int pid, int status,
|
||||
if (! pull_pid_from_list (&stopped_pids, new_pid))
|
||||
{
|
||||
/* The new child has a pending SIGSTOP. We can't affect it until it
|
||||
hits the SIGSTOP, but we're already attached.
|
||||
|
||||
It won't be a clone (we didn't ask for clones in the event mask)
|
||||
so we can just call waitpid and wait for the SIGSTOP. */
|
||||
hits the SIGSTOP, but we're already attached. */
|
||||
do {
|
||||
ret = waitpid (new_pid, &status, 0);
|
||||
ret = waitpid (new_pid, &status,
|
||||
(event == PTRACE_EVENT_CLONE) ? __WCLONE : 0);
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
if (ret == -1)
|
||||
perror_with_name ("waiting for new child");
|
||||
@ -423,8 +419,13 @@ linux_handle_extended_wait (int pid, int status,
|
||||
"wait returned unexpected status 0x%x", status);
|
||||
}
|
||||
|
||||
ourstatus->kind = (event == PTRACE_EVENT_FORK)
|
||||
? TARGET_WAITKIND_FORKED : TARGET_WAITKIND_VFORKED;
|
||||
if (event == PTRACE_EVENT_FORK)
|
||||
ourstatus->kind = TARGET_WAITKIND_FORKED;
|
||||
else if (event == PTRACE_EVENT_VFORK)
|
||||
ourstatus->kind = TARGET_WAITKIND_VFORKED;
|
||||
else
|
||||
ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
|
||||
|
||||
ourstatus->value.related_pid = new_pid;
|
||||
return inferior_ptid;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Native debugging support for GNU/Linux (LWP layer).
|
||||
Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
||||
Copyright 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
@ -18,6 +18,8 @@
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "target.h"
|
||||
|
||||
/* Structure describing an LWP. */
|
||||
|
||||
struct lwp_info
|
||||
@ -52,6 +54,11 @@ struct lwp_info
|
||||
/* Non-zero if we were stepping this LWP. */
|
||||
int step;
|
||||
|
||||
/* If WAITSTATUS->KIND != TARGET_WAITKIND_SPURIOUS, the waitstatus
|
||||
for this LWP's last event. This may correspond to STATUS above,
|
||||
or to a local variable in lin_lwp_wait. */
|
||||
struct target_waitstatus waitstatus;
|
||||
|
||||
/* Next LWP in list. */
|
||||
struct lwp_info *next;
|
||||
};
|
||||
@ -60,7 +67,6 @@ struct lwp_info
|
||||
system". */
|
||||
struct mem_attrib;
|
||||
struct target_ops;
|
||||
struct target_waitstatus;
|
||||
|
||||
extern int linux_proc_xfer_memory (CORE_ADDR addr, char *myaddr, int len,
|
||||
int write, struct mem_attrib *attrib,
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user