diff options
author | Pedro Alves <pedro@palves.net> | 2020-12-23 13:39:18 +0000 |
---|---|---|
committer | Pedro Alves <pedro@palves.net> | 2021-01-11 14:23:16 +0000 |
commit | 87183c0bd3858bdf61d4975a530d8663db4fabab (patch) | |
tree | 47786996d0d5d0f39d7459976858ca24850db8eb | |
parent | ea5159b92f95d80f77f49ffe7fb61dea4e747105 (diff) | |
download | gdb-87183c0bd3858bdf61d4975a530d8663db4fabab.zip gdb-87183c0bd3858bdf61d4975a530d8663db4fabab.tar.gz gdb-87183c0bd3858bdf61d4975a530d8663db4fabab.tar.bz2 |
Testcase for attaching in non-stop mode
This adds a testcase exercising attaching to a multi-threaded process,
in all combinations of:
- set non-stop on/off
- maint target non-stop off/on
- "attach" vs "attach &"
This exercises the bugs fixed in the two previous patches.
gdb/testsuite/ChangeLog:
* gdb.threads/attach-non-stop.c: New file.
* gdb.threads/attach-non-stop.exp: New file.
-rw-r--r-- | gdb/testsuite/gdb.threads/attach-non-stop.c | 58 | ||||
-rw-r--r-- | gdb/testsuite/gdb.threads/attach-non-stop.exp | 149 |
2 files changed, 207 insertions, 0 deletions
diff --git a/gdb/testsuite/gdb.threads/attach-non-stop.c b/gdb/testsuite/gdb.threads/attach-non-stop.c new file mode 100644 index 0000000..23a8b25 --- /dev/null +++ b/gdb/testsuite/gdb.threads/attach-non-stop.c @@ -0,0 +1,58 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2021 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 <assert.h> +#include <pthread.h> +#include <unistd.h> + +/* Number of threads we'll create. */ +static const int n_threads = 10; + +/* Entry point for threads. Loops forever. */ + +void * +thread_func (void *arg) +{ + while (1) + sleep (1); + + return NULL; +} + +int +main (int argc, char **argv) +{ + int i; + + alarm (30); + + /* Spawn the test threads. */ + for (i = 0; i < n_threads; ++i) + { + pthread_t child; + int rc; + + rc = pthread_create (&child, NULL, thread_func, NULL); + assert (rc == 0); + } + + while (1) + sleep (1); + + return 0; +} diff --git a/gdb/testsuite/gdb.threads/attach-non-stop.exp b/gdb/testsuite/gdb.threads/attach-non-stop.exp new file mode 100644 index 0000000..96b95b7 --- /dev/null +++ b/gdb/testsuite/gdb.threads/attach-non-stop.exp @@ -0,0 +1,149 @@ +# Copyright 2021 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 attaching to a multi-threaded process, in all combinations of: +# +# - set non-stop on/off +# - maint target non-stop off/on +# - "attach" vs "attach &" + +if {![can_spawn_for_attach]} { + return 0 +} + +standard_testfile + +# The test proper. See description above. + +proc test {target_non_stop non_stop cmd} { + global binfile srcfile + global gdb_prompt + global decimal + global GDBFLAGS + + # Number of threads started by the program. + set n_threads 10 + + save_vars { GDBFLAGS } { + append GDBFLAGS " -ex \"maint set target-non-stop $target_non_stop\"" + append GDBFLAGS " -ex \"set non-stop $non_stop\"" + clean_restart $binfile + } + + set test_spawn_id [spawn_wait_for_attach $binfile] + set testpid [spawn_id_get_pid $test_spawn_id] + + set attached 0 + set test "attach" + set any "\[^\r\n\]*" + + if {$cmd == "attach"} { + gdb_test_multiple "attach $testpid" $test { + -re "Attaching to program:${any}process $testpid\r\n.*$gdb_prompt " { + pass $test + set attached 1 + } + } + + if {!$attached} { + kill_wait_spawned_process $test_spawn_id + return + } + + if {$non_stop} { + # In non-stop, we will see one stop per thread after + # the prompt. + set stops 0 + set test "seen all stops" + for {set thread 1} { $thread <= $n_threads } { incr thread } { + gdb_test_multiple "" $test { + -re "Thread $::decimal ${any} stopped" { + incr stops + } + } + } + + # This we haven't seen all stops, then the + # gdb_test_multiple in the loop above will have + # already issued a FAIL. + if {$stops == $n_threads} { + pass $test + } + } + + gdb_test_multiple "info threads" "" { + -re "\\(running\\).*$gdb_prompt $" { + fail $gdb_test_name + } + -re "$gdb_prompt $" { + pass $gdb_test_name + } + } + } else { + gdb_test_multiple "attach $testpid &" $test { + -re "Attaching to program:${any}process $testpid\r\n.*$gdb_prompt " { + pass $test + set attached 1 + } + } + + if {!$attached} { + kill_wait_spawned_process $test_spawn_id + return + } + + set running_count 0 + gdb_test_multiple "info threads" "all threads running" { + -re "\\(running\\)" { + incr running_count + exp_continue + } + -re "Cannot execute this command while the target is running.*$gdb_prompt $" { + # Testing against a remote server that doesn't do + # non-stop mode. Explicitly interrupt. This doesn't + # test the same code paths in GDB, but it's still + # something. + gdb_test_multiple "interrupt" "" { + -re "$gdb_prompt " { + gdb_test_multiple "" $gdb_test_name { + -re "received signal SIGINT, Interrupt" { + pass $gdb_test_name + } + } + } + } + } + -re "$gdb_prompt $" { + gdb_assert {$running_count == ($n_threads + 1)} $gdb_test_name + } + } + } + + gdb_test "detach" "Detaching from.*" + + kill_wait_spawned_process $test_spawn_id +} + +if {[build_executable "failed to prepare" $testfile $srcfile {debug pthreads}] == -1} { + return -1 +} + +foreach_with_prefix target-non-stop {"off" "on"} { + foreach_with_prefix non-stop {"off" "on"} { + foreach_with_prefix cmd {"attach" "attach&"} { + test ${target-non-stop} ${non-stop} ${cmd} + } + } +} |