From 438ac09b47f7fbd1cf7b8dff0c2275546100c2a4 Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Mon, 8 Sep 2008 21:28:53 +0000 Subject: * inf-ttrace.c: Include (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 | 116 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 87 insertions(+), 29 deletions(-) (limited to 'gdb/inf-ttrace.c') diff --git a/gdb/inf-ttrace.c b/gdb/inf-ttrace.c index 3774b00..8284561 100644 --- a/gdb/inf-ttrace.c +++ b/gdb/inf-ttrace.c @@ -33,6 +33,7 @@ #include "gdb_string.h" #include #include +#include #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 resuming all threads, it's the current thread that should be + handled specially. */ + if (resume_all) + ptid = inferior_ptid; - 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); - } + 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 target_waitstatus *ourstatus) 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 *ignore) 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; -- cgit v1.1