diff options
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 6 | ||||
-rw-r--r-- | gdb/linux-nat.c | 5 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/testsuite/gdb.threads/stop-with-handle.c | 74 | ||||
-rw-r--r-- | gdb/testsuite/gdb.threads/stop-with-handle.exp | 51 |
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 |