gdbserver: Get the pid from /proc when attaching to a non-initial lwp
Commit Message
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(-)
@@ -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);
@@ -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;
}
@@ -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"