gdbserver: Get the pid from /proc when attaching to a non-initial lwp

Message ID 1398187705-17237-1-git-send-email-simon.marchi@ericsson.com
State Superseded
Delegated to: Pedro Alves
Headers

Commit Message

Simon Marchi April 22, 2014, 5:28 p.m. UTC
  gdbserver fails to attach to a second inferior that is multi-threaded.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=16255

For the second inferior (and so on), current_inferior is still set to the
first inferior when this code is ran. As a result, non-initial lwps of
the second inferior get assigned the pid of the first inferior.

One solution could be to switch current_inferior temporarily. Another
one (which I chose) is to go get the pid (tgid in the linux terminology)
in /proc.

I augmented the gdb.server/ext-attach.exp test case to attach to two
inferiors simultaneously and made the test program multi-threaded.

gdb/gdbserver/ChangeLog:

2014-04-22  Simon Marchi  <simon.marchi@ericsson.com>

	PR gdb/16255
	* linux-low.c (linux_attach_lwp_1): Get pid of non-initial lwp from
	from /proc.

gdb/testsuite/ChangeLog:

2014-04-22  Simon Marchi  <simon.marchi@ericsson.com>

	* gdb.server/ext-attach.c (thread_func): New function. Waits
	just like main ().
	(main): Start a second thread and join it.
	* gdb.server/ext-attach.exp: Start a second inferior and test
	attaching to it as well.
---
 gdb/gdbserver/linux-low.c               |  6 +-----
 gdb/testsuite/gdb.server/ext-attach.c   | 17 +++++++++++++++
 gdb/testsuite/gdb.server/ext-attach.exp | 38 +++++++++++++++++++++++----------
 3 files changed, 45 insertions(+), 16 deletions(-)
  

Patch

diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index c847c62..7fcf73e 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -672,11 +672,7 @@  linux_attach_lwp_1 (unsigned long lwpid, int initial)
     ptid = ptid_build (lwpid, lwpid, 0);
   else
     {
-      /* Note that extracting the pid from the current inferior is
-	 safe, since we're always called in the context of the same
-	 process as this new thread.  */
-      int pid = pid_of (current_inferior);
-      ptid = ptid_build (pid, lwpid, 0);
+      ptid = ptid_build (linux_proc_get_tgid (lwpid), lwpid, 0);
     }
 
   new_lwp = add_lwp (ptid);
diff --git a/gdb/testsuite/gdb.server/ext-attach.c b/gdb/testsuite/gdb.server/ext-attach.c
index 803d430..0fb0a64 100644
--- a/gdb/testsuite/gdb.server/ext-attach.c
+++ b/gdb/testsuite/gdb.server/ext-attach.c
@@ -19,13 +19,30 @@ 
    attached to by gdb.  It loops for a while, but not forever.  */
 
 #include <unistd.h>
+#include <pthread.h>
+
+static void *
+thread_func (void *arg)
+{
+  int i;
+
+  for (i = 0; i < 120; i++)
+    sleep (1);
+
+  return NULL;
+}
 
 int main ()
 {
   int i;
+  pthread_t thread;
+
+  pthread_create (&thread, NULL, thread_func, NULL);
 
   for (i = 0; i < 120; i++)
     sleep (1);
 
+  pthread_join (thread, NULL);
+
   return 0;
 }
diff --git a/gdb/testsuite/gdb.server/ext-attach.exp b/gdb/testsuite/gdb.server/ext-attach.exp
index 5f7bac4..2488b38 100644
--- a/gdb/testsuite/gdb.server/ext-attach.exp
+++ b/gdb/testsuite/gdb.server/ext-attach.exp
@@ -31,7 +31,7 @@  if [is_remote target] then {
     return 0
 }
 
-if {[prepare_for_testing $testfile.exp $testfile $srcfile debug]} {
+if {[prepare_for_testing $testfile.exp $testfile $srcfile {debug additional_flags=-lpthread}]} {
     return -1
 }
 
@@ -46,16 +46,18 @@  gdb_test_no_output "set remote exec-file $target_exec" "set remote exec-file"
 
 # Start the program running and then wait for a bit, to be sure
 # that it can be attached to.
-set testpid [eval exec $binfile &]
+set testpid1 [eval exec $binfile &]
+set testpid2 [eval exec $binfile &]
 exec sleep 2
 if { [istarget "*-*-cygwin*"] } {
-    # testpid is the Cygwin PID, GDB uses the Windows PID, which might be
+    # testpid{1,2} are the Cygwin PID, GDB uses the Windows PID, which might be
     # different due to the way fork/exec works.
-    set testpid [ exec ps -e | gawk "{ if (\$1 == $testpid) print \$4; }" ]
+    set testpid1 [ exec ps -e | gawk "{ if (\$1 == $testpid1) print \$4; }" ]
+    set testpid2 [ exec ps -e | gawk "{ if (\$1 == $testpid2) print \$4; }" ]
 }
 
-gdb_test "attach $testpid" \
-    "Attaching to program: .*, process $testpid.*(in|at).*" \
+gdb_test "attach $testpid1" \
+    "Attaching to program: .*, process $testpid1.*(in|at).*" \
     "attach to remote program 1"
 
 if { [gdb_target_supports_trace] } then {
@@ -71,10 +73,24 @@  gdb_test "backtrace" ".*main.*" "backtrace 1"
 gdb_test "detach" "Detaching from program.*process.*"
 gdb_test "backtrace" "No stack\\." "backtrace with no program"
 
-gdb_test "attach $testpid" \
-    "Attaching to program: .*, process $testpid.*(in|at).*" \
-    "attach to remote program 2"
-gdb_test "backtrace" ".*main.*" "backtrace 2"
+# Now try to attach again, and try to attach to two inferiors
+gdb_test "attach $testpid1" \
+    "Attaching to program: .*, process $testpid1.*(in|at).*" \
+    "attach to remote program 2.1"
+gdb_test "backtrace" ".*main.*" "backtrace 2.1"
+
+gdb_test "add-inferior -exec $target_exec" \
+    "Added inferior 2.*" \
+    "add second inferior"
+gdb_test "inferior 2" ".*Switching to inferior 2.*" "switch to second inferior"
+
+gdb_test "attach $testpid2" \
+    "Attaching to program: .*, process $testpid2.*(in|at).*" \
+    "attach to remote program 2.2"
+gdb_test "backtrace" ".*main.*" "backtrace 2.2"
+
+gdb_test "kill" "" "kill inferior 2" "Kill the program being debugged.*" "y"
+gdb_test "inferior 1" ".*Switching to inferior 1.*"
+gdb_test "kill" "" "kill inferior 1" "Kill the program being debugged.*" "y"
 
-gdb_test "kill" "" "kill" "Kill the program being debugged.*" "y"
 gdb_test_no_output "monitor exit"