231 lines
7.7 KiB
Diff
231 lines
7.7 KiB
Diff
http://post-office.corp.redhat.com/archives/debug-list/2016-April/msg00003.html
|
|
|
|
>From cb8bfeaa21a2df484d3c4c35cc6ea1c4b32cefc8 Mon Sep 17 00:00:00 2001
|
|
From: Pedro Alves <palves@redhat.com>
|
|
Date: Wed, 6 Apr 2016 15:07:49 +0100
|
|
Subject: [PATCH] Fix PR gdb/19828: gdb -p <process from a container>: internal
|
|
error
|
|
|
|
When GDB attaches to a process, it looks at the /proc/PID/task/ dir
|
|
for all clone threads of that process, and attaches to each of them.
|
|
|
|
Usually, if there is more than one clone thread, it means the program
|
|
is multi threaded and linked with pthreads. Thus when GDB soon after
|
|
attaching finds and loads a libthread_db matching the process, it'll
|
|
add a thread to the thread list for each of the initially found
|
|
lower-level LWPs.
|
|
|
|
If, however, GDB fails to find/load a matching libthread_db, nothing
|
|
is adding the LWPs to the thread list. And because of that, "detach"
|
|
hits an internal error:
|
|
|
|
(gdb) PASS: gdb.threads/clone-attach-detach.exp: fg attach 1: attach
|
|
info threads
|
|
Id Target Id Frame
|
|
* 1 LWP 6891 "clone-attach-de" 0x00007f87e5fd0790 in __nanosleep_nocancel () at ../sysdeps/unix/syscall-template.S:84
|
|
(gdb) FAIL: gdb.threads/clone-attach-detach.exp: fg attach 1: info threads shows two LWPs
|
|
detach
|
|
.../src/gdb/thread.c:1010: internal-error: is_executing: Assertion `tp' failed.
|
|
A problem internal to GDB has been detected,
|
|
further debugging may prove unreliable.
|
|
Quit this debugging session? (y or n)
|
|
FAIL: gdb.threads/clone-attach-detach.exp: fg attach 1: detach (GDB internal error)
|
|
|
|
>From here:
|
|
|
|
...
|
|
#8 0x00000000007ba7cc in internal_error (file=0x98ea68 ".../src/gdb/thread.c", line=1010, fmt=0x98ea30 "%s: Assertion `%s' failed.")
|
|
at .../src/gdb/common/errors.c:55
|
|
#9 0x000000000064bb83 in is_executing (ptid=...) at .../src/gdb/thread.c:1010
|
|
#10 0x00000000004c23bb in get_pending_status (lp=0x12c5cc0, status=0x7fffffffdc0c) at .../src/gdb/linux-nat.c:1235
|
|
#11 0x00000000004c2738 in detach_callback (lp=0x12c5cc0, data=0x0) at .../src/gdb/linux-nat.c:1317
|
|
#12 0x00000000004c1a2a in iterate_over_lwps (filter=..., callback=0x4c2599 <detach_callback>, data=0x0) at .../src/gdb/linux-nat.c:899
|
|
#13 0x00000000004c295c in linux_nat_detach (ops=0xe7bd30, args=0x0, from_tty=1) at .../src/gdb/linux-nat.c:1358
|
|
#14 0x000000000068284d in delegate_detach (self=0xe7bd30, arg1=0x0, arg2=1) at .../src/gdb/target-delegates.c:34
|
|
#15 0x0000000000694141 in target_detach (args=0x0, from_tty=1) at .../src/gdb/target.c:2241
|
|
#16 0x0000000000630582 in detach_command (args=0x0, from_tty=1) at .../src/gdb/infcmd.c:2975
|
|
...
|
|
|
|
Tested on x86-64 Fedora 23. Also confirmed the test passes against
|
|
gdbserver with with "maint set target-non-stop".
|
|
|
|
gdb/ChangeLog:
|
|
yyyy-mm-dd Pedro Alves <palves@redhat.com>
|
|
|
|
* linux-nat.c (attach_proc_task_lwp_callback): Add the thread to
|
|
GDB's thread list.
|
|
|
|
testsuite/ChangeLog:
|
|
yyyy-mm-dd Pedro Alves <palves@redhat.com>
|
|
|
|
* gdb.threads/clone-attach-detach.c: New file.
|
|
* gdb.threads/clone-attach-detach.exp: New file.
|
|
---
|
|
gdb/linux-nat.c | 5 ++
|
|
gdb/testsuite/gdb.threads/clone-attach-detach.c | 66 +++++++++++++++++++++++
|
|
gdb/testsuite/gdb.threads/clone-attach-detach.exp | 63 ++++++++++++++++++++++
|
|
3 files changed, 134 insertions(+)
|
|
create mode 100644 gdb/testsuite/gdb.threads/clone-attach-detach.c
|
|
create mode 100644 gdb/testsuite/gdb.threads/clone-attach-detach.exp
|
|
|
|
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
|
|
index 0829bcb..2025c19 100644
|
|
--- a/gdb/linux-nat.c
|
|
+++ b/gdb/linux-nat.c
|
|
@@ -1088,6 +1088,11 @@ attach_proc_task_lwp_callback (ptid_t ptid)
|
|
/* We need to wait for a stop before being able to make the
|
|
next ptrace call on this LWP. */
|
|
lp->must_set_ptrace_flags = 1;
|
|
+
|
|
+ /* Also add the LWP to gdb's thread list, in case a
|
|
+ matching libthread_db is not found (or the process uses
|
|
+ raw clone). */
|
|
+ add_thread (lp->ptid);
|
|
}
|
|
|
|
return 1;
|
|
diff --git a/gdb/testsuite/gdb.threads/clone-attach-detach.c b/gdb/testsuite/gdb.threads/clone-attach-detach.c
|
|
new file mode 100644
|
|
index 0000000..daa8f1f
|
|
--- /dev/null
|
|
+++ b/gdb/testsuite/gdb.threads/clone-attach-detach.c
|
|
@@ -0,0 +1,66 @@
|
|
+/* This testcase is part of GDB, the GNU debugger.
|
|
+
|
|
+ Copyright 2016 Free Software Foundation, Inc.
|
|
+
|
|
+ This program is free software; you can redistribute it and/or modify
|
|
+ it under the terms of the GNU General Public License as published by
|
|
+ the Free Software Foundation; either version 3 of the License, or
|
|
+ (at your option) any later version.
|
|
+
|
|
+ This program is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ GNU General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU General Public License
|
|
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
+*/
|
|
+
|
|
+#define _GNU_SOURCE
|
|
+#include <sched.h>
|
|
+#include <assert.h>
|
|
+#include <stdlib.h>
|
|
+#include <sys/types.h>
|
|
+#include <sys/wait.h>
|
|
+#include <unistd.h>
|
|
+
|
|
+#define STACK_SIZE 0x1000
|
|
+
|
|
+int clone_pid;
|
|
+
|
|
+static int
|
|
+clone_fn (void *unused)
|
|
+{
|
|
+ /* Wait for alarm. */
|
|
+ while (1)
|
|
+ sleep (1);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int
|
|
+main (int argc, char **argv)
|
|
+{
|
|
+ unsigned char *stack;
|
|
+ int res;
|
|
+
|
|
+ alarm (300);
|
|
+
|
|
+ stack = malloc (STACK_SIZE);
|
|
+ assert (stack != NULL);
|
|
+
|
|
+#define CLONE_FLAGS (CLONE_THREAD | CLONE_SIGHAND | CLONE_VM)
|
|
+
|
|
+#ifdef __ia64__
|
|
+ clone_pid = __clone2 (clone_fn, stack, STACK_SIZE, CLONE_FLAGS, NULL);
|
|
+#else
|
|
+ clone_pid = clone (clone_fn, stack + STACK_SIZE, CLONE_FLAGS, NULL);
|
|
+#endif
|
|
+
|
|
+ assert (clone_pid > 0);
|
|
+
|
|
+ /* Wait for alarm. */
|
|
+ while (1)
|
|
+ sleep (1);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
diff --git a/gdb/testsuite/gdb.threads/clone-attach-detach.exp b/gdb/testsuite/gdb.threads/clone-attach-detach.exp
|
|
new file mode 100644
|
|
index 0000000..0652108
|
|
--- /dev/null
|
|
+++ b/gdb/testsuite/gdb.threads/clone-attach-detach.exp
|
|
@@ -0,0 +1,63 @@
|
|
+# This testcase is part of GDB, the GNU debugger.
|
|
+
|
|
+# Copyright 2016 Free Software Foundation, Inc.
|
|
+
|
|
+# This program is free software; you can redistribute it and/or modify
|
|
+# it under the terms of the GNU General Public License as published by
|
|
+# the Free Software Foundation; either version 3 of the License, or
|
|
+# (at your option) any later version.
|
|
+#
|
|
+# This program is distributed in the hope that it will be useful,
|
|
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+# GNU General Public License for more details.
|
|
+#
|
|
+# You should have received a copy of the GNU General Public License
|
|
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
+
|
|
+# Test attach / detach from a process that uses raw clone. We use raw
|
|
+# clone as proxy for when libthread_db is not available.
|
|
+
|
|
+# This only works on targets with the Linux kernel.
|
|
+if ![istarget *-*-linux*] {
|
|
+ return
|
|
+}
|
|
+
|
|
+if {![can_spawn_for_attach]} {
|
|
+ return 0
|
|
+}
|
|
+
|
|
+standard_testfile
|
|
+
|
|
+if [prepare_for_testing "failed to prepare" $testfile $srcfile {debug}] {
|
|
+ return -1
|
|
+}
|
|
+
|
|
+clean_restart ${binfile}
|
|
+
|
|
+set test_spawn_id [spawn_wait_for_attach $binfile]
|
|
+set testpid [spawn_id_get_pid $test_spawn_id]
|
|
+
|
|
+# Native/gdbserver.
|
|
+set thread_re "(LWP $decimal|Thread )"
|
|
+
|
|
+# Try attach / detach a few times, in case GDB ends up with stale
|
|
+# state after detaching.
|
|
+
|
|
+set attempts 3
|
|
+for {set attempt 1} {$attempt <= $attempts} {incr attempt} {
|
|
+ with_test_prefix "fg attach $attempt" {
|
|
+
|
|
+ gdb_test "attach $testpid" \
|
|
+ "Attaching to program.*process $testpid.*" \
|
|
+ "attach"
|
|
+
|
|
+ gdb_test "info threads" \
|
|
+ "1.*${thread_re}.*\r\n.*2.*${thread_re}.*" \
|
|
+ "info threads shows two LWPs"
|
|
+
|
|
+ gdb_test "detach" "Detaching from .*, process $testpid"
|
|
+ }
|
|
+}
|
|
+
|
|
+kill_wait_spawned_process $test_spawn_id
|
|
--
|
|
2.5.5
|
|
|