From: Daniel Jacobowitz <drow@false.org>
To: Andrew STUBBS <andrew.stubbs@st.com>
Cc: gdb-patches@sources.redhat.com
Subject: Re: [PATCH] Disable thread specific breakpoints when thread dies
Date: Fri, 20 Jan 2006 22:41:00 -0000 [thread overview]
Message-ID: <20060120224115.GB16076@nevyn.them.org> (raw)
In-Reply-To: <43CBC6EB.9080904@st.com>
On Mon, Jan 16, 2006 at 04:16:43PM +0000, Andrew STUBBS wrote:
> Andrew STUBBS wrote:
> >Now onto figuring out why it doesn't work....
>
> The smoking gun seems to be here:
>
> [From linux-thread-db.c]
>
> 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;
> }
Nice catch - although there's a second smoking gun besides this one,
which is that linux-nat.c won't delete threads that are the current
inferior_ptid. With good reason. GDB absolutely falls apart when
you do that.
I think the long term fix for the latter is going to involve some
serious surgery on the notion of a current global inferior_ptid.
But until that happens, here's a workaround confined to the Linux
native code. The big advantage over calling prune_threads is we don't
need to make a lot of expensive syscalls.
Any comments? Does this work for you? It does seem to avoid inserting
the breakpoint unnecessarily, as I'd expect.
--
Daniel Jacobowitz
CodeSourcery
2006-01-20 Daniel Jacobowitz <dan@codesourcery.com>
* linux-nat.c (struct saved_ptids, threads_to_delete)
(record_dead_thread, prune_lwps, find_thread_from_lwp)
(exit_lwp): New.
(linux_nat_resume): Call prune_lwps.
(wait_lwp, linux_nat_wait): Call exit_lwp.
Index: linux-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/linux-nat.c,v
retrieving revision 1.36
diff -u -p -r1.36 linux-nat.c
--- linux-nat.c 4 Jan 2006 19:34:58 -0000 1.36
+++ linux-nat.c 20 Jan 2006 22:36:46 -0000
@@ -868,6 +868,92 @@ iterate_over_lwps (int (*callback) (stru
return NULL;
}
+/* Record a PTID for later deletion. */
+
+struct saved_ptids
+{
+ ptid_t ptid;
+ struct saved_ptids *next;
+};
+static struct saved_ptids *threads_to_delete;
+
+static void
+record_dead_thread (ptid_t ptid)
+{
+ struct saved_ptids *p = xmalloc (sizeof (struct saved_ptids));
+ p->ptid = ptid;
+ p->next = threads_to_delete;
+ threads_to_delete = p;
+}
+
+/* Delete any dead threads which are not the current thread. */
+
+static void
+prune_lwps (void)
+{
+ struct saved_ptids **p = &threads_to_delete;
+
+ while (*p)
+ if (! ptid_equal ((*p)->ptid, inferior_ptid))
+ {
+ struct saved_ptids *tmp = *p;
+ delete_thread (tmp->ptid);
+ *p = tmp->next;
+ xfree (tmp);
+ }
+ else
+ p = &(*p)->next;
+}
+
+/* Callback for iterate_over_threads that finds a thread corresponding
+ to the given LWP. */
+
+static int
+find_thread_from_lwp (struct thread_info *thr, void *dummy)
+{
+ ptid_t *ptid_p = dummy;
+
+ if (GET_LWP (thr->ptid) && GET_LWP (thr->ptid) == GET_LWP (*ptid_p))
+ return 1;
+ else
+ return 0;
+}
+
+/* Handle the exit of a single thread LP. */
+
+static void
+exit_lwp (struct lwp_info *lp)
+{
+ if (in_thread_list (lp->ptid))
+ {
+ /* Core GDB cannot deal with us deleting the current thread. */
+ if (!ptid_equal (lp->ptid, inferior_ptid))
+ delete_thread (lp->ptid);
+ else
+ record_dead_thread (lp->ptid);
+ printf_unfiltered (_("[%s exited]\n"),
+ target_pid_to_str (lp->ptid));
+ }
+ else
+ {
+ /* Even if LP->PTID is not in the global GDB thread list, the
+ LWP may be - with an additional thread ID. We don't need
+ to print anything in this case; thread_db is in use and
+ already took care of that. But it didn't delete the thread
+ in order to handle zombies correctly. */
+
+ struct thread_info *thr;
+
+ thr = iterate_over_threads (find_thread_from_lwp, &lp->ptid);
+ if (thr && !ptid_equal (thr->ptid, inferior_ptid))
+ delete_thread (thr->ptid);
+ else
+ record_dead_thread (thr->ptid);
+ }
+
+ delete_lwp (lp->ptid);
+}
+
/* Attach to the LWP specified by PID. If VERBOSE is non-zero, print
a message telling the user that a new LWP has been added to the
process. */
@@ -1121,6 +1207,8 @@ linux_nat_resume (ptid_t ptid, int step,
signo ? strsignal (signo) : "0",
target_pid_to_str (inferior_ptid));
+ prune_lwps ();
+
/* A specific PTID means `step only this process id'. */
resume_all = (PIDGET (ptid) == -1);
@@ -1321,16 +1409,7 @@ wait_lwp (struct lwp_info *lp)
if (thread_dead)
{
- if (in_thread_list (lp->ptid))
- {
- /* Core GDB cannot deal with us deleting the current thread. */
- if (!ptid_equal (lp->ptid, inferior_ptid))
- delete_thread (lp->ptid);
- printf_unfiltered (_("[%s exited]\n"),
- target_pid_to_str (lp->ptid));
- }
-
- delete_lwp (lp->ptid);
+ exit_lwp (lp);
return 0;
}
@@ -2117,16 +2196,6 @@ retry:
/* Check if the thread has exited. */
if ((WIFEXITED (status) || WIFSIGNALED (status)) && num_lwps > 1)
{
- if (in_thread_list (lp->ptid))
- {
- /* Core GDB cannot deal with us deleting the current
- thread. */
- if (!ptid_equal (lp->ptid, inferior_ptid))
- delete_thread (lp->ptid);
- printf_unfiltered (_("[%s exited]\n"),
- target_pid_to_str (lp->ptid));
- }
-
/* If this is the main thread, we must stop all threads and
verify if they are still alive. This is because in the nptl
thread model, there is no signal issued for exiting LWPs
@@ -2148,7 +2217,7 @@ retry:
"LLW: %s exited.\n",
target_pid_to_str (lp->ptid));
- delete_lwp (lp->ptid);
+ exit_lwp (lp);
/* If there is at least one more LWP, then the exit signal
was not the end of the debugged application and should be
@@ -2170,21 +2239,12 @@ retry:
has stopped. A similar check is made in stop_wait_callback(). */
if (num_lwps > 1 && !linux_nat_thread_alive (lp->ptid))
{
- if (in_thread_list (lp->ptid))
- {
- /* Core GDB cannot deal with us deleting the current
- thread. */
- if (!ptid_equal (lp->ptid, inferior_ptid))
- delete_thread (lp->ptid);
- printf_unfiltered (_("[%s exited]\n"),
- target_pid_to_str (lp->ptid));
- }
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
"LLW: %s exited.\n",
target_pid_to_str (lp->ptid));
- delete_lwp (lp->ptid);
+ exit_lwp (lp);
/* Make sure there is at least one thread running. */
gdb_assert (iterate_over_lwps (running_callback, NULL));
next prev parent reply other threads:[~2006-01-20 22:41 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-11-09 19:06 Andrew STUBBS
2005-11-13 21:13 ` Daniel Jacobowitz
2005-11-14 16:34 ` Andrew STUBBS
2005-11-14 17:11 ` Daniel Jacobowitz
2005-11-15 18:55 ` Andrew STUBBS
2005-11-16 16:23 ` Andrew STUBBS
2005-11-17 4:22 ` Daniel Jacobowitz
2005-11-17 16:34 ` Andrew STUBBS
2006-01-12 16:25 ` Andrew STUBBS
2006-01-13 4:19 ` Michael Snyder
2006-01-13 4:31 ` Daniel Jacobowitz
2006-01-12 16:27 ` Daniel Jacobowitz
2006-01-13 17:35 ` Andrew STUBBS
2006-01-13 20:11 ` Mark Kettenis
2006-01-14 15:46 ` Daniel Jacobowitz
2006-01-14 15:56 ` Mark Kettenis
2006-01-14 16:06 ` Daniel Jacobowitz
2006-01-16 12:57 ` Andrew STUBBS
2006-01-16 16:19 ` Andrew STUBBS
2006-01-20 14:56 ` Andrew STUBBS
2006-01-20 15:00 ` Daniel Jacobowitz
2006-01-20 22:41 ` Daniel Jacobowitz [this message]
2006-02-02 2:30 ` Daniel Jacobowitz
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=20060120224115.GB16076@nevyn.them.org \
--to=drow@false.org \
--cc=andrew.stubbs@st.com \
--cc=gdb-patches@sources.redhat.com \
/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