aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog6
-rw-r--r--gdb/linux-nat.c5
-rw-r--r--gdb/testsuite/ChangeLog5
-rw-r--r--gdb/testsuite/gdb.threads/stop-with-handle.c74
-rw-r--r--gdb/testsuite/gdb.threads/stop-with-handle.exp51
5 files changed, 140 insertions, 1 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index bcf1de9..534e9ff 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,11 @@
2019-10-03 Andrew Burgess <andrew.burgess@embecosm.com>
+ * linux-nat.c (linux_nat_filter_event): Don't ignore SIGSTOP if we
+ have just sent the thread a SIGSTOP and are waiting for it to
+ arrive.
+
+2019-10-03 Andrew Burgess <andrew.burgess@embecosm.com>
+
* btrace.c (btrace_add_pc): Remove whitespace before the template
parameter in 'std::vector <...>'.
(parse_xml_btrace_block): Likewise.
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index cd5cf18..0a8ea5b 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -3146,9 +3146,12 @@ linux_nat_filter_event (int lwpid, int status)
/* When using hardware single-step, we need to report every signal.
Otherwise, signals in pass_mask may be short-circuited
- except signals that might be caused by a breakpoint. */
+ except signals that might be caused by a breakpoint, or SIGSTOP
+ if we sent the SIGSTOP and are waiting for it to arrive. */
if (!lp->step
&& WSTOPSIG (status) && sigismember (&pass_mask, WSTOPSIG (status))
+ && (WSTOPSIG (status) != SIGSTOP
+ || !find_thread_ptid (lp->ptid)->stop_requested)
&& !linux_wstatus_maybe_breakpoint (status))
{
linux_resume_one_lwp (lp, lp->step, signo);
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index acc930a..867db05 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2019-10-03 Andrew Burgess <andrew.burgess@embecosm.com>
+
+ * gdb.threads/stop-with-handle.c: New file.
+ * gdb.threads/stop-with-handle.exp: New file.
+
2019-10-03 Tom de Vries <tdevries@suse.de>
PR testsuite/25059
diff --git a/gdb/testsuite/gdb.threads/stop-with-handle.c b/gdb/testsuite/gdb.threads/stop-with-handle.c
new file mode 100644
index 0000000..335676b
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/stop-with-handle.c
@@ -0,0 +1,74 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2019 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/>. */
+
+#include <stdio.h>
+#include <pthread.h>
+#include <unistd.h>
+
+/* A place to record the thread. */
+pthread_t the_thread;
+
+/* The worker thread just spins forever. */
+void*
+thread_worker (void *payload)
+{
+ while (1)
+ {
+ sleep (1);
+ }
+
+ return NULL;
+}
+
+/* Create a worker thread. */
+int
+spawn_thread ()
+{
+ if (pthread_create (&the_thread, NULL, thread_worker, NULL))
+ {
+ fprintf (stderr, "Unable to create thread.\n");
+ return 0;
+ }
+ return 1;
+}
+
+/* A place for GDB to place a breakpoint. */
+void __attribute__((used))
+breakpt ()
+{
+ /* Nothing. */
+}
+
+/* Create a worker thread that just spins forever, then enter a loop
+ periodically calling the BREAKPT function. */
+int
+main()
+{
+ /* Ensure we stop if GDB crashes and DejaGNU fails to kill us. */
+ alarm (10);
+
+ spawn_thread ();
+
+ while (1)
+ {
+ sleep (1);
+
+ breakpt ();
+ }
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.threads/stop-with-handle.exp b/gdb/testsuite/gdb.threads/stop-with-handle.exp
new file mode 100644
index 0000000..ad69ec1
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/stop-with-handle.exp
@@ -0,0 +1,51 @@
+# Copyright 2019 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/>.
+
+# This test covers a case where SIGSTOP has been configured to be
+# passed to the target with GDB's 'handle' command, and then a
+# multi-threaded inferior encounters an event that causes all theads
+# to be stopped.
+#
+# The problem that (used) to exist was that GDB would see the SIGSTOP,
+# but decide to ignore the signal based on the handle table.
+
+standard_testfile
+
+if {[prepare_for_testing "failed to prepare" \
+ "${testfile}" "${srcfile}" {debug pthreads}]} {
+ return -1
+}
+
+if ![runto_main] then {
+ fail "can't run to main"
+ return 0
+}
+
+# Have SIGSTOP sent to the inferior.
+gdb_test "handle SIGSTOP nostop noprint pass" \
+ [multi_line \
+ "Signal\[ \t\]+Stop\[ \t\]+Print\[ \t\]+Pass to program\[ \t\]+Description" \
+ "SIGSTOP\[ \t\]+No\[ \t\]+No\[ \t\]+Yes\[ \t\]+Stopped \\(signal\\)"]
+
+# Create a breakpoint, and when we hit it automatically finish the
+# current frame.
+gdb_breakpoint breakpt
+
+# When the bug triggers this continue never completes. GDB hits the
+# breakpoint in thread 1, and then tries to stop the second thread by
+# sending it SIGSTOP. GDB sees the SIGSTOP arrive in thread 2 but
+# incorrect decides to pass the SIGSTOP to the thread rather than
+# bringing the thread to a stop.
+gdb_continue_to_breakpoint breakpt