aboutsummaryrefslogtreecommitdiff
path: root/gdb/gdbserver/linux-low.c
diff options
context:
space:
mode:
authorLuis Machado <luisgpm@br.ibm.com>2011-08-24 12:17:39 +0000
committerLuis Machado <luisgpm@br.ibm.com>2011-08-24 12:17:39 +0000
commite3deef738cf04479b2114ddb3b1dfb5f18a9b409 (patch)
tree7c92cb02c6ecbfee317de67f85804649464c5a6b /gdb/gdbserver/linux-low.c
parent13da1c9782f523debe697aa1415b7b4f96fe4f93 (diff)
downloadgdb-e3deef738cf04479b2114ddb3b1dfb5f18a9b409.zip
gdb-e3deef738cf04479b2114ddb3b1dfb5f18a9b409.tar.gz
gdb-e3deef738cf04479b2114ddb3b1dfb5f18a9b409.tar.bz2
Stop threads when attaching to a PID that is the tgid.
Diffstat (limited to 'gdb/gdbserver/linux-low.c')
-rw-r--r--gdb/gdbserver/linux-low.c75
1 files changed, 72 insertions, 3 deletions
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 0aab032..94f785c 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -26,6 +26,7 @@
#include <sys/param.h>
#include <sys/ptrace.h>
#include "linux-ptrace.h"
+#include "linux-procfs.h"
#include <signal.h>
#include <sys/ioctl.h>
#include <fcntl.h>
@@ -586,7 +587,9 @@ linux_attach_lwp_1 (unsigned long lwpid, int initial)
}
if (initial)
- /* NOTE/FIXME: This lwp might have not been the tgid. */
+ /* If lwp is the tgid, we handle adding existing threads later.
+ Otherwise we just add lwp without bothering about any other
+ threads. */
ptid = ptid_build (lwpid, lwpid, 0);
else
{
@@ -621,8 +624,10 @@ linux_attach_lwp_1 (unsigned long lwpid, int initial)
In this case we want the process thread to stop.
This is handled by having linux_attach set last_resume_kind ==
resume_stop after we return.
- ??? If the process already has several threads we leave the other
- threads running.
+
+ If the pid we are attaching to is also the tgid, we attach to and
+ stop all the existing threads. Otherwise, we attach to pid and
+ ignore any other threads in the same group as this pid.
3) GDB is connecting to gdbserver and is requesting an enumeration of all
existing threads.
@@ -646,9 +651,14 @@ linux_attach_lwp (unsigned long lwpid)
linux_attach_lwp_1 (lwpid, 0);
}
+/* Attach to PID. If PID is the tgid, attach to it and all
+ of its threads. */
+
int
linux_attach (unsigned long pid)
{
+ /* Attach to PID. We will check for other threads
+ soon. */
linux_attach_lwp_1 (pid, 1);
linux_add_process (pid, 1);
@@ -662,6 +672,65 @@ linux_attach (unsigned long pid)
thread->last_resume_kind = resume_stop;
}
+ if (linux_proc_get_tgid (pid) == pid)
+ {
+ DIR *dir;
+ char pathname[128];
+
+ sprintf (pathname, "/proc/%ld/task", pid);
+
+ dir = opendir (pathname);
+
+ if (!dir)
+ {
+ fprintf (stderr, "Could not open /proc/%ld/task.\n", pid);
+ fflush (stderr);
+ }
+ else
+ {
+ /* At this point we attached to the tgid. Scan the task for
+ existing threads. */
+ unsigned long lwp;
+ int new_threads_found;
+ int iterations = 0;
+ struct dirent *dp;
+
+ while (iterations < 2)
+ {
+ new_threads_found = 0;
+ /* Add all the other threads. While we go through the
+ threads, new threads may be spawned. Cycle through
+ the list of threads until we have done two iterations without
+ finding new threads. */
+ while ((dp = readdir (dir)) != NULL)
+ {
+ /* Fetch one lwp. */
+ lwp = strtoul (dp->d_name, NULL, 10);
+
+ /* Is this a new thread? */
+ if (lwp
+ && find_thread_ptid (ptid_build (pid, lwp, 0)) == NULL)
+ {
+ linux_attach_lwp_1 (lwp, 0);
+ new_threads_found++;
+
+ if (debug_threads)
+ fprintf (stderr, "\
+Found and attached to new lwp %ld\n", lwp);
+ }
+ }
+
+ if (!new_threads_found)
+ iterations++;
+ else
+ iterations = 0;
+
+ rewinddir (dir);
+ }
+ closedir (dir);
+ }
+ }
+
return 0;
}