From: Pedro Alves <pedro@codesourcery.com>
To: gdb-patches@sourceware.org
Cc: "John David Anglin" <dave@hiauly1.hia.nrc.ca>
Subject: Re: ttrace: Protocal error
Date: Sat, 09 Aug 2008 22:46:00 -0000 [thread overview]
Message-ID: <200808092345.23905.pedro@codesourcery.com> (raw)
In-Reply-To: <200808091551.17013.pedro@codesourcery.com>
[-- Attachment #1: Type: text/plain, Size: 2804 bytes --]
On Saturday 09 August 2008 15:51:16, Pedro Alves wrote:
> inf_ttrace_wait ()
> ...
> case TTEVT_LWP_EXIT:
> if (print_thread_events)
> printf_unfiltered (_("[%s exited]\n"), target_pid_to_str (ptid));
> ti = find_thread_pid (ptid);
> gdb_assert (ti != NULL);
> ((struct inf_ttrace_private_thread_info *)ti->private)->dying = 1;
> inf_ttrace_num_lwps--;
> (1) ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid),
> ptid_get_lwp (ptid), TT_NOPC, 0, 0);
> /* If we don't return -1 here, core GDB will re-add the thread. */
> ptid = minus_one_ptid;
> break;
> ...
>
> /* Make sure all threads within the process are stopped. */
> (2) if (ttrace (TT_PROC_STOP, tts.tts_pid, 0, 0, 0, 0) == -1)
> perror_with_name (("ttrace"));
>
> return ptid;
> }
>
>
> It seems to me, that for some reason, in most cases, the inferior was slow
> enough that when you reach (2), the dying thread hadn't exited
> yet. The TT_PROC_STOP call stops all lwps of the process, the
> dying one included, I would think. In that case, you still need the
> resume on the dying thread in inf_ttrace_wait. Otherwise, you *may*
> get this bug back, depending on how the OS is waking waiting processes:
> So, to minimise the possible race, how about:
>
> - still try to resume a dying lwp. Ignore the errno you
> were originally seeing in that case (only).
> - on resume failure, delete it from GDBs thread table.
> - if by any chance, the lwp exits, and the inferior spawn a
> new lwp, and the OS reuses the same lwpid of the lwp we knew
> was dying, we delete the dying lwp, and add the new one.
> If the OS is reusing the id, the original lwp has to be gone.
> This is just an add_thread call, as that is already handled by it
> internally (*).
> - If the thread is still alive, but is dying, let that show
> in "info threads". The linux pthread support implementation
> also does this.
This is what the attached patch does. In adition to what is
described above, I'm checking if any dying thread is now gone
after stopping the whole process. I'm checking for lwp "aliveness"
with sending signal 0. I hope it works as expected against
ttrace stopped threads, otherwise, I'd need another way to detect
if the lwp is still alive.
With this change, we no longer unconditionaly delete the dying
lwps after the first resume. This is to prevent that another event
that was already queued is handled and GDB stopping the whole process
before the dying thread having a chance to die. In this case, we'll
still need another resume in the dying lwp -- until it really exits.
Hope I haven't broken anything badly. I've never in my live logged in
to an HP-UX system, so wear sunglasses.
--
Pedro Alves
[-- Attachment #2: fix_daves_bug.diff --]
[-- Type: text/x-diff, Size: 6398 bytes --]
2008-08-09 Pedro Alves <pedro@codesourcery.com>
* inf-ttrace.c: Include <signal.h>
(inf_ttrace_delete_dead_threads_callback): New.
(inf_ttrace_resume_lwp): New.
(inf_ttrace_resume_callback, inf_ttrace_resume): Rewrite. Don't
delete dying threads until they are really dead.
(inf_ttrace_wait): After stopping the whole process, delete any
dying thread that is really dead by now.
(inf_ttrace_thread_alive): Return 1.
(inf_ttrace_extra_thread_info): New.
(inf_ttrace_target): Register inf_ttrace_extra_thread_info.
---
gdb/inf-ttrace.c | 118 +++++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 88 insertions(+), 30 deletions(-)
Index: src/gdb/inf-ttrace.c
===================================================================
--- src.orig/gdb/inf-ttrace.c 2008-08-09 15:10:27.000000000 +0100
+++ src/gdb/inf-ttrace.c 2008-08-09 23:24:52.000000000 +0100
@@ -33,6 +33,7 @@
#include "gdb_string.h"
#include <sys/mman.h>
#include <sys/ttrace.h>
+#include <signal.h>
#include "inf-child.h"
#include "inf-ttrace.h"
@@ -801,52 +802,85 @@ inf_ttrace_kill (void)
target_mourn_inferior ();
}
+/* Check is a dying thread is dead by now, and delete it from GDBs
+ thread list if so. */
static int
-inf_ttrace_resume_callback (struct thread_info *info, void *arg)
+inf_ttrace_delete_dead_threads_callback (struct thread_info *info, void *arg)
{
- if (!ptid_equal (info->ptid, inferior_ptid) && !is_exited (info->ptid))
- {
- pid_t pid = ptid_get_pid (info->ptid);
- lwpid_t lwpid = ptid_get_lwp (info->ptid);
+ lwpid_t lwpid;
+ struct inf_ttrace_private_thread_info *p;
- if (ttrace (TT_LWP_CONTINUE, pid, lwpid, TT_NOPC, 0, 0) == -1)
- perror_with_name (("ttrace"));
- }
+ if (is_exited (info->ptid))
+ return 0;
+
+ lwpid = ptid_get_lwp (info->ptid);
+ p = (struct inf_ttrace_private_thread_info *) info->private;
+
+ /* Check if an lwp that was dying is still there or not. */
+ if (p->dying && (kill (lwpid, 0) == -1))
+ /* It's gone now. */
+ delete_thread (info->ptid);
return 0;
}
+/* Resume the lwp pointed to by INFO, with REQUEST, and pass it signal
+ SIG. */
+
+static void
+inf_ttrace_resume_lwp (struct thread_info *info, ttreq_t request, int sig)
+{
+ pid_t pid = ptid_get_pid (info->ptid);
+ lwpid_t lwpid = ptid_get_lwp (info->ptid);
+
+ if (ttrace (request, pid, lwpid, TT_NOPC, sig, 0) == -1)
+ {
+ struct inf_ttrace_private_thread_info *p
+ = (struct inf_ttrace_private_thread_info *) info->private;
+ if (p->dying && errno == EPROTO)
+ /* This is expected, it means the dying lwp is really gone
+ by now. If ttrace had an event to inform the debugger
+ the lwp is really gone, this wouldn't be needed. */
+ delete_thread (info->ptid);
+ else
+ /* This was really unexpected. */
+ perror_with_name (("ttrace"));
+ }
+}
+
+/* Callback for iterate_over_threads. */
+
static int
-inf_ttrace_delete_dying_threads_callback (struct thread_info *info, void *arg)
+inf_ttrace_resume_callback (struct thread_info *info, void *arg)
{
- if (((struct inf_ttrace_private_thread_info *)info->private)->dying == 1)
- delete_thread (info->ptid);
+ if (!ptid_equal (info->ptid, inferior_ptid) && !is_exited (info->ptid))
+ inf_ttrace_resume_lwp (info, TT_LWP_CONTINUE, 0);
+
return 0;
}
static void
inf_ttrace_resume (ptid_t ptid, int step, enum target_signal signal)
{
- pid_t pid = ptid_get_pid (ptid);
- lwpid_t lwpid = ptid_get_lwp (ptid);
+ int resume_all;
ttreq_t request = step ? TT_LWP_SINGLE : TT_LWP_CONTINUE;
int sig = target_signal_to_host (signal);
+ struct thread_info *info;
- if (pid == -1)
- {
- pid = ptid_get_pid (inferior_ptid);
- lwpid = ptid_get_lwp (inferior_ptid);
- }
+ /* A specific PTID means `step only this process id'. */
+ resume_all = (ptid_equal (ptid, minus_one_ptid));
- if (ttrace (request, pid, lwpid, TT_NOPC, sig, 0) == -1)
- perror_with_name (("ttrace"));
-
- if (ptid_equal (ptid, minus_one_ptid))
- {
- /* Let all the other threads run too. */
- iterate_over_threads (inf_ttrace_resume_callback, NULL);
- iterate_over_threads (inf_ttrace_delete_dying_threads_callback, NULL);
- }
+ /* If resuming all threads, it's the current thread that should be
+ handled specially. */
+ if (resume_all)
+ ptid = inferior_ptid;
+
+ info = thread_find_pid (ptid);
+ inf_ttrace_resume_lwp (info, request, sig);
+
+ if (resume_all)
+ /* Let all the other threads run too. */
+ iterate_over_threads (inf_ttrace_resume_callback, NULL);
}
static ptid_t
@@ -1075,6 +1109,16 @@ inf_ttrace_wait (ptid_t ptid, struct tar
if (ttrace (TT_PROC_STOP, tts.tts_pid, 0, 0, 0, 0) == -1)
perror_with_name (("ttrace"));
+ /* Now that the whole process is stopped, check if any dying thread
+ is really dead by now. If a dying thread is still alive, it will
+ be stopped too, and will still show up in `info threads', tagged
+ with "(Exiting)". We could make `info threads' prune dead
+ threads instead via inf_ttrace_thread_alive, but doing this here
+ has the advantage that a frontend is notificed sooner of thread
+ exits. Note that a dying lwp is still alive, it still has to be
+ resumed, like any other lwp. */
+ iterate_over_threads (inf_ttrace_delete_dead_threads_callback, NULL);
+
return ptid;
}
@@ -1145,9 +1189,22 @@ inf_ttrace_files_info (struct target_ops
static int
inf_ttrace_thread_alive (ptid_t ptid)
{
- struct thread_info *ti;
- ti = find_thread_pid (ptid);
- return !(((struct inf_ttrace_private_thread_info *)ti->private)->dying);
+ return 1;
+}
+
+/* Return a string describing the state of the thread specified by
+ INFO. */
+
+static char *
+inf_ttrace_extra_thread_info (struct thread_info *info)
+{
+ struct inf_ttrace_private_thread_info* private =
+ (struct inf_ttrace_private_thread_info *) info->private;
+
+ if (private != NULL && private->dying)
+ return "Exiting";
+
+ return NULL;
}
static char *
@@ -1188,6 +1245,7 @@ inf_ttrace_target (void)
t->to_follow_fork = inf_ttrace_follow_fork;
t->to_mourn_inferior = inf_ttrace_mourn_inferior;
t->to_thread_alive = inf_ttrace_thread_alive;
+ t->to_extra_thread_info = inf_ttrace_extra_thread_info;
t->to_pid_to_str = inf_ttrace_pid_to_str;
t->to_xfer_partial = inf_ttrace_xfer_partial;
next prev parent reply other threads:[~2008-08-09 22:46 UTC|newest]
Thread overview: 64+ messages / expand[flat|nested] mbox.gz Atom feed top
2001-09-10 0:30 [RFA] patch to add 'maint profile-gdb' command Jason Molenda
2001-09-10 8:48 ` Andrew Cagney
2001-09-10 8:58 ` Eli Zaretskii
2001-09-10 9:04 ` Andrew Cagney
2001-09-10 11:52 ` Jason Molenda
2001-09-10 13:43 ` Eli Zaretskii
2001-09-10 13:59 ` Jason Molenda
2001-09-11 0:38 ` Eli Zaretskii
[not found] ` <no.id>
1999-06-15 20:10 ` Missing routines: gdb/top.c John David Anglin
2001-09-11 1:37 ` [RFA] patch to add 'maint profile-gdb' command Jason Molenda
2001-09-11 1:57 ` Eli Zaretskii
2001-09-12 0:00 ` Jason Molenda
2001-09-12 6:00 ` Eli Zaretskii
2001-09-12 7:42 ` Jason Molenda
2001-09-12 9:06 ` Eli Zaretskii
2001-09-12 11:58 ` Tom Tromey
2001-09-12 13:16 ` Jason Molenda
2008-08-06 19:24 ` [patch] Don't set DT_HP_DEBUG_PRIVATE in solib-pa64.c John David Anglin
2008-08-06 19:49 ` Mark Kettenis
2008-08-06 20:09 ` John David Anglin
2008-08-06 23:10 ` John David Anglin
2008-08-07 21:39 ` [patch] Only force private mapping of shared libraries in solib-som.c on HP-UX 10 and earlier John David Anglin
2008-08-08 10:48 ` Joel Brobecker
2008-08-08 15:34 ` John David Anglin
2008-08-09 14:37 ` Joel Brobecker
2008-08-09 18:59 ` John David Anglin
2008-08-08 19:30 ` ttrace: Protocal error John David Anglin
2008-08-08 20:16 ` John David Anglin
2008-08-09 14:52 ` Pedro Alves
2008-08-09 15:34 ` John David Anglin
2008-08-09 18:49 ` John David Anglin
2008-08-09 22:45 ` Pedro Alves
2008-08-09 22:46 ` Pedro Alves [this message]
2008-08-09 22:51 ` Pedro Alves
2008-08-09 23:19 ` John David Anglin
2008-08-09 22:48 ` Pedro Alves
2008-08-09 14:53 ` Joel Brobecker
2008-08-09 23:40 ` John David Anglin
2008-08-10 0:46 ` [4/7] Adjust the ttrace target (HP-UX) to always register the John David Anglin
2008-09-15 2:08 ` [PATCH] Fix dwarf register column to gdb register mapping John David Anglin
2008-09-15 2:24 ` [PATCH] Fix hppa_linux_sigtramp_frame_unwind_cache John David Anglin
2001-09-12 11:28 ` [RFA] patch to add 'maint profile-gdb' command Andrew Cagney
2001-09-12 11:43 ` Andrew Cagney
2001-09-16 17:45 ` [RFA] Version 2 of " Jason Molenda
2001-09-17 22:39 ` Andrew Cagney
2001-09-18 17:52 ` Fernando Nasser
2001-09-18 17:56 ` Andrew Cagney
2001-09-19 7:11 ` Fernando Nasser
2001-09-19 7:28 ` Eli Zaretskii
2001-09-19 9:29 ` Fernando Nasser
2001-09-19 11:30 ` Eli Zaretskii
2001-09-19 11:41 ` Andrew Cagney
2001-09-19 11:53 ` Kevin Buettner
[not found] ` <200109170536.HAA21988@is.elta.co.il>
2001-09-17 15:08 ` Michael Snyder
2001-09-17 22:43 ` Andrew Cagney
2001-09-17 23:59 ` Eli Zaretskii
2001-09-24 13:33 ` Jason Molenda
2001-09-24 14:41 ` Andrew Cagney
2001-09-24 14:58 ` Eli Zaretskii
2001-09-24 15:13 ` Andrew Cagney
2001-09-24 14:53 ` Eli Zaretskii
2008-08-08 17:24 [4/7] Adjust the ttrace target (HP-UX) to always register the main thread Pedro Alves
2008-08-08 18:34 ` ttrace: Protocal error John David Anglin
2008-08-08 20:02 ` Pedro Alves
2008-08-08 20:49 ` John David Anglin
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=200808092345.23905.pedro@codesourcery.com \
--to=pedro@codesourcery.com \
--cc=dave@hiauly1.hia.nrc.ca \
--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