Stop threads when attaching to a PID that is the tgid.
authorLuis Machado <luisgpm@br.ibm.com>
Wed, 24 Aug 2011 12:17:39 +0000 (12:17 +0000)
committerLuis Machado <luisgpm@br.ibm.com>
Wed, 24 Aug 2011 12:17:39 +0000 (12:17 +0000)
gdb/gdbserver/ChangeLog
gdb/gdbserver/Makefile.in
gdb/gdbserver/linux-low.c

index 7176e8b35b8194233b6fa6f4175ac058195be48c..8bdb5b52f8c8595fb077e6fe506a91cf0d5c04e0 100644 (file)
@@ -1,3 +1,11 @@
+2011-08-24  Luis Machado  <lgustavo@codesourcery.com>
+
+       * 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  <lgustavo@codesourcery.com>
 
        * configure.srv: Add linux-procfs.o dependencies.
 2011-08-24  Luis Machado  <lgustavo@codesourcery.com>
 
        * configure.srv: Add linux-procfs.o dependencies.
index 70f011add904824bf1f0de79e63ca526be6bbebd..01729ce9b1df0163e5f74f7762aaa0c2767957a0 100644 (file)
@@ -354,6 +354,8 @@ linux_ptrace_h = $(srcdir)/../common/linux-ptrace.h
 
 gdb_thread_db_h = $(srcdir)/../common/gdb_thread_db.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
 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
 
 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
 
 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)
 
 
 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) \
        $(CC) -c $(CPPFLAGS) $(INTERNAL_CFLAGS) $< @USE_THREAD_DB@
 
 linux-arm-low.o: linux-arm-low.c $(linux_low_h) $(server_h) \
index 0aab032e944b18a15f8057f6a452c5b6f915fd13..94f785c2a64d15792734eabf354465a5d2724166 100644 (file)
@@ -26,6 +26,7 @@
 #include <sys/param.h>
 #include <sys/ptrace.h>
 #include "linux-ptrace.h"
 #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>
 #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)
     }
 
   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
     {
     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.
        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.
 
      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);
 }
 
   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)
 {
 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);
 
   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;
     }
 
       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;
 }
 
   return 0;
 }