1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
# Copyright 2021-2023 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
}
}
}
# If 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}
}
}
}
|