2011-09-02 Pedro Alves <pedro@codesourcery.com>
* linux-nat.c (in_pid_list_p): New. (linux_record_stopped_pid): Delete. (lin_lwp_attach_lwp): Check if PTRACE_ATTACH failed because we're already attached to the LWP. Return an indication if so. (linux_nat_filter_event): Adjust. * linux-thread-db.c (attach_thread): Handle lin_lwp_attach_lwp returning an indication to ignore this thread.
This commit is contained in:
parent
68e77c9e30
commit
84636d2874
@ -1,3 +1,13 @@
|
||||
2011-09-02 Pedro Alves <pedro@codesourcery.com>
|
||||
|
||||
* linux-nat.c (in_pid_list_p): New.
|
||||
(linux_record_stopped_pid): Delete.
|
||||
(lin_lwp_attach_lwp): Check if PTRACE_ATTACH failed because we're
|
||||
already attached to the LWP. Return an indication if so.
|
||||
(linux_nat_filter_event): Adjust.
|
||||
* linux-thread-db.c (attach_thread): Handle lin_lwp_attach_lwp
|
||||
returning an indication to ignore this thread.
|
||||
|
||||
2011-09-02 Pedro Alves <pedro@codesourcery.com>
|
||||
|
||||
* top.c: Include interps.h.
|
||||
|
@ -330,6 +330,17 @@ add_to_pid_list (struct simple_pid_list **listp, int pid, int status)
|
||||
*listp = new_pid;
|
||||
}
|
||||
|
||||
static int
|
||||
in_pid_list_p (struct simple_pid_list *list, int pid)
|
||||
{
|
||||
struct simple_pid_list *p;
|
||||
|
||||
for (p = list; p != NULL; p = p->next)
|
||||
if (p->pid == pid)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pull_pid_from_list (struct simple_pid_list **listp, int pid, int *statusp)
|
||||
{
|
||||
@ -348,12 +359,6 @@ pull_pid_from_list (struct simple_pid_list **listp, int pid, int *statusp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
linux_record_stopped_pid (int pid, int status)
|
||||
{
|
||||
add_to_pid_list (&stopped_pids, pid, status);
|
||||
}
|
||||
|
||||
|
||||
/* A helper function for linux_test_for_tracefork, called after fork (). */
|
||||
|
||||
@ -1386,20 +1391,25 @@ linux_nat_post_attach_wait (ptid_t ptid, int first, int *cloned,
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Attach to the LWP specified by PID. Return 0 if successful or -1
|
||||
if the new LWP could not be attached. */
|
||||
/* Attach to the LWP specified by PID. Return 0 if successful, -1 if
|
||||
the new LWP could not be attached, or 1 if we're already auto
|
||||
attached to this thread, but haven't processed the
|
||||
PTRACE_EVENT_CLONE event of its parent thread, so we just ignore
|
||||
its existance, without considering it an error. */
|
||||
|
||||
int
|
||||
lin_lwp_attach_lwp (ptid_t ptid)
|
||||
{
|
||||
struct lwp_info *lp;
|
||||
sigset_t prev_mask;
|
||||
int lwpid;
|
||||
|
||||
gdb_assert (is_lwp (ptid));
|
||||
|
||||
block_child_signals (&prev_mask);
|
||||
|
||||
lp = find_lwp_pid (ptid);
|
||||
lwpid = GET_LWP (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
|
||||
@ -1407,12 +1417,48 @@ lin_lwp_attach_lwp (ptid_t ptid)
|
||||
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) && lp == NULL)
|
||||
if (lwpid != GET_PID (ptid) && lp == NULL)
|
||||
{
|
||||
int status, cloned = 0, signalled = 0;
|
||||
|
||||
if (ptrace (PTRACE_ATTACH, GET_LWP (ptid), 0, 0) < 0)
|
||||
if (ptrace (PTRACE_ATTACH, lwpid, 0, 0) < 0)
|
||||
{
|
||||
if (linux_supports_tracefork_flag)
|
||||
{
|
||||
/* If we haven't stopped all threads when we get here,
|
||||
we may have seen a thread listed in thread_db's list,
|
||||
but not processed the PTRACE_EVENT_CLONE yet. If
|
||||
that's the case, ignore this new thread, and let
|
||||
normal event handling discover it later. */
|
||||
if (in_pid_list_p (stopped_pids, lwpid))
|
||||
{
|
||||
/* We've already seen this thread stop, but we
|
||||
haven't seen the PTRACE_EVENT_CLONE extended
|
||||
event yet. */
|
||||
restore_child_signals_mask (&prev_mask);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int new_pid;
|
||||
int status;
|
||||
|
||||
/* See if we've got a stop for this new child
|
||||
pending. If so, we're already attached. */
|
||||
new_pid = my_waitpid (lwpid, &status, WNOHANG);
|
||||
if (new_pid == -1 && errno == ECHILD)
|
||||
new_pid = my_waitpid (lwpid, &status, __WCLONE | WNOHANG);
|
||||
if (new_pid != -1)
|
||||
{
|
||||
if (WIFSTOPPED (status))
|
||||
add_to_pid_list (&stopped_pids, lwpid, status);
|
||||
|
||||
restore_child_signals_mask (&prev_mask);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we fail to attach to the thread, issue a warning,
|
||||
but continue. One way this can happen is if thread
|
||||
creation is interrupted; as of Linux kernel 2.6.19, a
|
||||
@ -3084,7 +3130,7 @@ linux_nat_filter_event (int lwpid, int status, int options)
|
||||
from waitpid before or after the event is. */
|
||||
if (WIFSTOPPED (status) && !lp)
|
||||
{
|
||||
linux_record_stopped_pid (lwpid, status);
|
||||
add_to_pid_list (&stopped_pids, lwpid, status);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1140,9 +1140,25 @@ attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
|
||||
|
||||
/* Under GNU/Linux, we have to attach to each and every thread. */
|
||||
if (target_has_execution
|
||||
&& tp == NULL
|
||||
&& lin_lwp_attach_lwp (BUILD_LWP (ti_p->ti_lid, GET_PID (ptid))) < 0)
|
||||
return 0;
|
||||
&& tp == NULL)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = lin_lwp_attach_lwp (BUILD_LWP (ti_p->ti_lid, GET_PID (ptid)));
|
||||
if (res < 0)
|
||||
{
|
||||
/* Error, stop iterating. */
|
||||
return 0;
|
||||
}
|
||||
else if (res > 0)
|
||||
{
|
||||
/* Pretend this thread doesn't exist yet, and keep
|
||||
iterating. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Otherwise, we sucessfully attached to the thread. */
|
||||
}
|
||||
|
||||
/* Construct the thread's private data. */
|
||||
private = xmalloc (sizeof (struct private_thread_info));
|
||||
|
Loading…
x
Reference in New Issue
Block a user