From e3deef738cf04479b2114ddb3b1dfb5f18a9b409 Mon Sep 17 00:00:00 2001 From: Luis Machado Date: Wed, 24 Aug 2011 12:17:39 +0000 Subject: [PATCH] Stop threads when attaching to a PID that is the tgid. --- gdb/gdbserver/ChangeLog | 8 +++++ gdb/gdbserver/Makefile.in | 8 ++++- gdb/gdbserver/linux-low.c | 75 +++++++++++++++++++++++++++++++++++++-- 3 files changed, 87 insertions(+), 4 deletions(-) diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 7176e8b35b8..8bdb5b52f8c 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,11 @@ +2011-08-24 Luis Machado + + * linux-low.c: Include linux-procfs.h. + (linux_attach_lwp_1): Update comments. + (linux_attach): Scan for existing threads when attaching to a + process that is the tgid. + * Makefile.in: Update dependencies. + 2011-08-24 Luis Machado * configure.srv: Add linux-procfs.o dependencies. diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in index 70f011add90..01729ce9b1d 100644 --- a/gdb/gdbserver/Makefile.in +++ b/gdb/gdbserver/Makefile.in @@ -354,6 +354,8 @@ linux_ptrace_h = $(srcdir)/../common/linux-ptrace.h gdb_thread_db_h = $(srcdir)/../common/gdb_thread_db.h +linux_procfs_h = $(srcdir)/../common/linux-procfs.h + lynx_low_h = $(srcdir)/lynx-low.h $(srcdir)/server.h nto_low_h = $(srcdir)/nto-low.h @@ -405,6 +407,9 @@ gdbreplay.o: gdbreplay.c config.h signals.o: ../common/signals.c $(server_h) $(signals_def) $(CC) -c $(CPPFLAGS) $(INTERNAL_CFLAGS) $< -DGDBSERVER +linux-procfs.o: ../common/linux-procfs.c $(server_h) + $(CC) -c $(CPPFLAGS) $(INTERNAL_CFLAGS) $< -DGDBSERVER + common-utils.o: ../common/common-utils.c $(server_h) $(CC) -c $(CPPFLAGS) $(INTERNAL_CFLAGS) $< -DGDBSERVER @@ -443,7 +448,8 @@ i386-low.o: i386-low.c $(i386_low_h) $(server_h) $(target_h) i387-fp.o: i387-fp.c $(server_h) -linux-low.o: linux-low.c $(linux_low_h) $(linux_ptrace_h) $(server_h) $(linux_osdata_h) +linux-low.o: linux-low.c $(linux_low_h) $(linux_ptrace_h) $(linux_procfs_h) \ + $(server_h) $(linux_osdata_h) $(CC) -c $(CPPFLAGS) $(INTERNAL_CFLAGS) $< @USE_THREAD_DB@ linux-arm-low.o: linux-arm-low.c $(linux_low_h) $(server_h) \ diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index 0aab032e944..94f785c2a64 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -26,6 +26,7 @@ #include #include #include "linux-ptrace.h" +#include "linux-procfs.h" #include #include #include @@ -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; } -- 2.30.2