diff options
Diffstat (limited to 'gdb/testsuite')
7 files changed, 546 insertions, 0 deletions
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index bd8cf44..e088b9b 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,5 +1,14 @@ 2014-07-25 Pedro Alves <palves@redhat.com> + * gdb.threads/signal-command-handle-nopass.c: New file. + * gdb.threads/signal-command-handle-nopass.exp: New file. + * gdb.threads/signal-command-multiple-signals-pending.c: New file. + * gdb.threads/signal-command-multiple-signals-pending.exp: New file. + * gdb.threads/signal-delivered-right-thread.c: New file. + * gdb.threads/signal-delivered-right-thread.exp: New file. + +2014-07-25 Pedro Alves <palves@redhat.com> + * gdb.base/double-prompt-target-event-error.exp (cancel_pagination_in_target_event): Remove '-notransfer <return>' match. diff --git a/gdb/testsuite/gdb.threads/signal-command-handle-nopass.c b/gdb/testsuite/gdb.threads/signal-command-handle-nopass.c new file mode 100644 index 0000000..abca2f9 --- /dev/null +++ b/gdb/testsuite/gdb.threads/signal-command-handle-nopass.c @@ -0,0 +1,49 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2014 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 <unistd.h> +#include <stdlib.h> +#include <pthread.h> +#include <signal.h> + +void +handler (int sig) +{ +} + +void * +thread_function (void *arg) +{ + volatile unsigned int i = 1; + + while (i != 0) + usleep (1); +} + +int +main (void) +{ + pthread_t child_thread; + int i; + + signal (SIGUSR1, handler); + pthread_create (&child_thread, NULL, thread_function, NULL); + pthread_join (child_thread, NULL); + + return 0; +} diff --git a/gdb/testsuite/gdb.threads/signal-command-handle-nopass.exp b/gdb/testsuite/gdb.threads/signal-command-handle-nopass.exp new file mode 100644 index 0000000..3ea9cf8 --- /dev/null +++ b/gdb/testsuite/gdb.threads/signal-command-handle-nopass.exp @@ -0,0 +1,78 @@ +# Copyright (C) 2014 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 that an explicit "signal FOO" delivers FOO even if "handle" for +# that same signal is set to "nopass". Also make sure the signal is +# delivered to the right thread, even if GDB has to step over a +# breakpoint in some other thread first. + +if [target_info exists gdb,nosignals] { + verbose "Skipping ${testfile}.exp because of nosignals." + return -1 +} + +standard_testfile + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \ + executable { debug }] != "" } { + return -1 +} + +# Run the test proper. STEP_OVER indicates whether we leave in place +# a breakpoint that needs to be stepped over when we explicitly +# request a signal be delivered with the "signal" command. + +proc test { step_over } { + global srcfile binfile + + with_test_prefix "step-over $step_over" { + clean_restart ${binfile} + + if ![runto_main] then { + fail "Can't run to main" + return 0 + } + + gdb_test "handle SIGUSR1 stop print nopass" + + gdb_test "b thread_function" "Breakpoint .* at .*$srcfile.*" + gdb_test "continue" "thread_function.*" "stopped in thread" + + # Thread 2 is stopped at a breakpoint. If we leave the + # breakpoint in place, GDB needs to move thread 2 past the + # breakpoint before delivering the signal to thread 1. We + # want to be sure that GDB doesn't mistakenly deliver the + # signal to thread 1 while doing that. + if { $step_over == "no" } { + delete_breakpoints + } + + gdb_test "break handler" "Breakpoint .* at .*$srcfile.*" + + gdb_test "thread 1" "Switching to thread 1.*" + + set pattern "\\\* 1\[ \t\]+Thread.*" + + gdb_test "info threads" $pattern "thread 1 selected" + + gdb_test "signal SIGUSR1" "handler .*" + + gdb_test "info threads" $pattern "thread 1 got the signal" + } +} + +foreach stepover {"yes" "no"} { + test $stepover +} diff --git a/gdb/testsuite/gdb.threads/signal-command-multiple-signals-pending.c b/gdb/testsuite/gdb.threads/signal-command-multiple-signals-pending.c new file mode 100644 index 0000000..2fc5f53 --- /dev/null +++ b/gdb/testsuite/gdb.threads/signal-command-multiple-signals-pending.c @@ -0,0 +1,98 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2014 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 <unistd.h> +#include <stdlib.h> +#include <pthread.h> +#include <signal.h> + +pthread_barrier_t barrier; +sig_atomic_t got_sigusr1; +sig_atomic_t got_sigusr2; + +void +handler_sigusr1 (int sig) +{ + got_sigusr1 = 1; +} + +void +handler_sigusr2 (int sig) +{ + got_sigusr2 = 1; +} + +void * +thread_function (void *arg) +{ + volatile unsigned int count = 1; + + pthread_barrier_wait (&barrier); + + while (count++ != 0) + { + if (got_sigusr1 && got_sigusr2) + break; + usleep (1); + } +} + +void +all_threads_started (void) +{ +} + +void +all_threads_signalled (void) +{ +} + +void +end (void) +{ +} + +int +main (void) +{ + pthread_t child_thread[2]; + int i; + + signal (SIGUSR1, handler_sigusr1); + signal (SIGUSR2, handler_sigusr2); + + pthread_barrier_init (&barrier, NULL, 3); + + for (i = 0; i < 2; i++) + pthread_create (&child_thread[i], NULL, thread_function, NULL); + + pthread_barrier_wait (&barrier); + + all_threads_started (); + + pthread_kill (child_thread[0], SIGUSR1); + pthread_kill (child_thread[1], SIGUSR2); + + all_threads_signalled (); + + for (i = 0; i < 2; i++) + pthread_join (child_thread[i], NULL); + + end (); + return 0; +} diff --git a/gdb/testsuite/gdb.threads/signal-command-multiple-signals-pending.exp b/gdb/testsuite/gdb.threads/signal-command-multiple-signals-pending.exp new file mode 100644 index 0000000..b5ec00a --- /dev/null +++ b/gdb/testsuite/gdb.threads/signal-command-multiple-signals-pending.exp @@ -0,0 +1,166 @@ +# Copyright (C) 2014 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 that "signal FOO" behaves correctly when we have multiple +# threads that have stopped for a signal. + +if [target_info exists gdb,nosignals] { + verbose "Skipping ${testfile}.exp because of nosignals." + return -1 +} + +standard_testfile + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \ + executable { debug }] != "" } { + return -1 +} + +# Run the test proper. SCHEDLOCK indicates which variant (around +# scheduler-locking) of the test to perform. + +proc test { schedlock } { + global srcfile binfile + + with_test_prefix "schedlock $schedlock" { + clean_restart ${binfile} + + if ![runto_main] then { + fail "Can't run to main" + return 0 + } + + gdb_test "handle SIGUSR1 stop print pass" + gdb_test "handle SIGUSR2 stop print pass" + + gdb_test "break all_threads_started" "Breakpoint .* at .*$srcfile.*" + gdb_test "continue" "all_threads_started.*" + + # Using schedlock, let the main thread queue a signal for each + # non-main thread. + gdb_test_no_output "set scheduler-locking on" + + gdb_test "break all_threads_signalled" "Breakpoint .* at .*$srcfile.*" + gdb_test "continue" "all_threads_signalled.*" + + gdb_test "info threads" "\\\* 1\[ \t\]+Thread.*" "thread 1 selected" + + # With schedlock still enabled, let each thread report its + # signal. + + gdb_test "thread 3" "Switching to thread 3.*" + gdb_test "continue" "Program received signal SIGUSR2.*" "stop with SIGUSR2" + gdb_test "thread 2" "Switching to thread 2.*" + gdb_test "continue" "Program received signal SIGUSR1.*" "stop with SIGUSR1" + + gdb_test "break handler_sigusr1" "Breakpoint .* at .*$srcfile.*" + gdb_test "break handler_sigusr2" "Breakpoint .* at .*$srcfile.*" + + set handler_re "Breakpoint .*, handler_sigusr. \\(sig=.*\\) at .*" + + # Now test the "signal" command with either scheduler locking + # enabled or disabled. + + if { $schedlock == "off" } { + # With scheduler locking off, switch to the main thread + # and issue "signal 0". "signal 0" should then warn that + # two threads have signals that will be delivered. When + # we let the command proceed, a signal should be + # delivered, and thus the corresponding breakpoint in the + # signal handler should trigger. + + gdb_test_no_output "set scheduler-locking off" + gdb_test "thread 1" "Switching to thread 1.*" + + set queried 0 + set test "signal command queries" + gdb_test_multiple "signal 0" $test { + -re "stopped with.*stopped with.*stopped with.*Continue anyway.*y or n. $" { + fail "$test (too many threads noted)" + set queried 1 + } + -re "stopped with signal SIGUSR.*\r\nContinuing .*still deliver .*Continue anyway.*y or n. $" { + pass $test + set queried 1 + } + -re "Continue anyway.*y or n. $" { + fail "$test (no threads noted)" + set queried 1 + } + } + + # Continuing should stop in one of the signal handlers. + # Which thread runs first is not determinate. + if {$queried} { + gdb_test "y" "$handler_re" "one signal delivered" + } + + # Continuing a second time should stop in the other + # handler. + with_test_prefix "second signal" { + gdb_test "continue" "$handler_re" "signal delivered" + } + } else { + # With scheduler locking on, stay with thread 2 selected, + # and try to deliver its signal explicitly. The "signal" + # command should then warn that one other thread has a + # signal that will be delivered. When we let the command + # proceed, the current thread's signal should be + # delivered, and thus the corresponding breakpoint in the + # signal handler should trigger. + gdb_test "signal SIGUSR1" \ + "Breakpoint .*, handler_sigusr1 \\(sig=.*\\) at .*" \ + "signal command does not query, signal delivered" + + with_test_prefix "second signal" { + # The other thread had stopped for a signal too, and + # it wasn't resumed yet. Disabling schedlock and + # trying "signal 0" from the main thread should warn + # again. + gdb_test_no_output "set scheduler-locking off" + + set queried 0 + set test "signal command queries" + gdb_test_multiple "signal 0" $test { + -re "stopped with.*stopped with.*Continue anyway.*y or n. $" { + fail "$test (too many threads noted)" + set queried 1 + } + -re "stopped with signal SIGUSR.*\r\nContinuing .*still deliver .*Continue anyway.*y or n. $" { + pass $test + set queried 1 + } + -re "Continue anyway.*y or n. $" { + fail "$test (no threads noted)" + set queried 1 + } + } + + if {$queried} { + gdb_test "y" "Breakpoint .*, handler_sigusr2 \\(sig=.*\\) at .*" "signal delivered" + } + } + } + + # Both threads got their signal. Continuing again should + # neither intercept nor deliver any other signal. + gdb_test "b end" "Breakpoint .* at .*$srcfile.*" + gdb_test "continue" "end .*" "no more signals" + } +} + +foreach schedlock {"off" "on"} { + test $schedlock +} diff --git a/gdb/testsuite/gdb.threads/signal-delivered-right-thread.c b/gdb/testsuite/gdb.threads/signal-delivered-right-thread.c new file mode 100644 index 0000000..66b68a8 --- /dev/null +++ b/gdb/testsuite/gdb.threads/signal-delivered-right-thread.c @@ -0,0 +1,61 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2014 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 <unistd.h> +#include <stdlib.h> +#include <pthread.h> +#include <signal.h> + +pthread_barrier_t barrier; + +void +handler (int sig) +{ +} + +void * +thread_function (void *arg) +{ + pthread_barrier_wait (&barrier); + + while (1) + usleep (1); +} + +int +main (void) +{ + pthread_t child_thread[2]; + int i; + + signal (SIGUSR1, handler); + + pthread_barrier_init (&barrier, NULL, 3); + + for (i = 0; i < 2; i++) + pthread_create (&child_thread[i], NULL, thread_function, NULL); + + pthread_barrier_wait (&barrier); + + pthread_kill (child_thread[0], SIGUSR1); + + for (i = 0; i < 2; i++) + pthread_join (child_thread[i], NULL); + + return 0; +} diff --git a/gdb/testsuite/gdb.threads/signal-delivered-right-thread.exp b/gdb/testsuite/gdb.threads/signal-delivered-right-thread.exp new file mode 100644 index 0000000..4243495 --- /dev/null +++ b/gdb/testsuite/gdb.threads/signal-delivered-right-thread.exp @@ -0,0 +1,85 @@ +# Copyright (C) 2014 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/>. */ + +if [target_info exists gdb,nosignals] { + verbose "Skipping ${testfile}.exp because of nosignals." + return -1 +} + +standard_testfile + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \ + executable { debug }] != "" } { + return -1 +} + +# Run test proper. COMMAND indicates whether to resume the inferior +# with "signal 0" or "continue". + +proc test { command } { + global srcfile binfile + + with_test_prefix "$command" { + clean_restart ${binfile} + + if ![runto_main] then { + fail "Can't run to main" + return 0 + } + + gdb_test "handle SIGUSR1 stop print pass" + + gdb_test "continue" "Program received signal SIGUSR1.*" "stop with SIGUSR1" + + set pattern "\\\* 2\[ \t\]+Thread.*" + + gdb_test "info threads" $pattern "thread 2 intercepted signal" + + gdb_test "break handler" "Breakpoint .* at .*$srcfile.*" + + gdb_test "thread 1" "Switching to thread 1.*" + + if { $command == "continue" } { + gdb_test "continue" "handler .*" + } elseif { $command == "signal 0" } { + set queried 0 + set test "signal 0 queries" + gdb_test_multiple "signal 0" $test { + -re "stopped with.*stopped with.*Continue anyway.*y or n. $" { + fail "$test (multiple threads noted)" + set queried 1 + } + -re "stopped with signal SIGUSR1.*\r\nContinuing .*still deliver .*Continue anyway.*y or n. $" { + pass $test + set queried 1 + } + -re "Continue anyway.*y or n. $" { + fail "$test (no threads noted)" + set queried 1 + } + } + + if {$queried} { + gdb_test "y" "handler .*" "signal is delivered" + } + } + + gdb_test "info threads" $pattern "thread 2 got the signal" + } +} + +foreach command {"continue" "signal 0"} { + test $command +} |