1# Copyright (C) 2016-2020 Free Software Foundation, Inc. 2 3# This program is free software; you can redistribute it and/or modify 4# it under the terms of the GNU General Public License as published by 5# the Free Software Foundation; either version 3 of the License, or 6# (at your option) any later version. 7# 8# This program is distributed in the hope that it will be useful, 9# but WITHOUT ANY WARRANTY; without even the implied warranty of 10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11# GNU General Public License for more details. 12# 13# You should have received a copy of the GNU General Public License 14# along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16# Regression test for PR gdb/18360. Test that "interrupt -a" while 17# some thread is stepping over a breakpoint behaves as expected. 18 19standard_testfile 20 21if {[prepare_for_testing "failed to prepare" $testfile $srcfile \ 22 {debug pthreads}] == -1} { 23 return -1 24} 25 26if {![runto_main]} { 27 fail "can't run to main" 28 return -1 29} 30 31# Read the number of threads out of the inferior. 32set NUM_THREADS [get_integer_valueof "num_threads" -1] 33 34# Account for the main thread. 35incr NUM_THREADS 36 37# Run command and wait for the prompt, without end anchor. 38 39proc gdb_test_no_anchor {cmd} { 40 global gdb_prompt 41 42 gdb_test_multiple $cmd $cmd { 43 -re "$gdb_prompt " { 44 pass $cmd 45 } 46 -re "infrun:" { 47 exp_continue 48 } 49 } 50} 51 52# Enable/disable debugging. 53 54proc enable_debug {enable} { 55 56 # Comment out to debug problems with the test. 57 return 58 59 gdb_test_no_anchor "set debug infrun $enable" 60 gdb_test_no_anchor "set debug displaced $enable" 61} 62 63# If RESULT is not zero, make the caller return RESULT. 64 65proc return_if_nonzero { result } { 66 if {$result != 0} { 67 return -code return $result 68 } 69} 70 71# Do one iteration of "c -a& -> interrupt -a". Return zero on sucess, 72# and non-zero if some test fails. 73 74proc test_one_iteration {} { 75 global gdb_prompt 76 global NUM_THREADS 77 global decimal 78 79 set saw_continuing 0 80 set test "continue -a &" 81 return_if_nonzero [gdb_test_multiple $test $test { 82 -re "Continuing.\r\n" { 83 set saw_continuing 1 84 exp_continue 85 } 86 -re "$gdb_prompt " { 87 if ![gdb_assert $saw_continuing $test] { 88 return 1 89 } 90 } 91 -re "infrun:" { 92 exp_continue 93 } 94 }] 95 96 set running_count 0 97 set test "all threads are running" 98 return_if_nonzero [gdb_test_multiple "info threads" $test { 99 -re "Thread \[^\r\n\]* \\(running\\)" { 100 incr running_count 101 exp_continue 102 } 103 -re "$gdb_prompt " { 104 if ![gdb_assert {$running_count == $NUM_THREADS} $test] { 105 return 1 106 } 107 } 108 -re "infrun:" { 109 exp_continue 110 } 111 }] 112 113 set test "interrupt -a" 114 return_if_nonzero [gdb_test_multiple $test $test { 115 -re "$gdb_prompt " { 116 pass $test 117 } 118 -re "infrun:" { 119 exp_continue 120 } 121 }] 122 123 set stopped_count 0 124 set test "wait for stops" 125 # Don't return on failure here, in order to let "info threads" put 126 # useful info in gdb.log. 127 gdb_test_multiple "" $test { 128 -re "Thread $decimal \[^\r\n\]*stopped" { 129 incr stopped_count 130 if {$stopped_count != $NUM_THREADS} { 131 exp_continue 132 } 133 } 134 -re "$gdb_prompt " { 135 gdb_assert {$stopped_count == $NUM_THREADS} $test 136 } 137 -re "infrun:" { 138 exp_continue 139 } 140 } 141 142 # Check if all threads are seen as stopped with "info 143 # threads". It's a bit redundant with the test above, but 144 # it's useful to have this in the gdb.log if the above ever 145 # happens to fail. 146 set running_count 0 147 set test "all threads are stopped" 148 return_if_nonzero [gdb_test_multiple "info threads" $test { 149 -re "Thread \[^\r\n\]* \\(running\\)" { 150 incr running_count 151 exp_continue 152 } 153 -re "$gdb_prompt " { 154 if ![gdb_assert {$running_count == 0} $test] { 155 return 1 156 } 157 } 158 }] 159 160 return 0 161} 162 163# The test driver proper. If DISPLACED is "on", turn on displaced 164# stepping. If "off", turn it off. 165 166proc testdriver {displaced} { 167 global binfile 168 global GDBFLAGS 169 170 save_vars { GDBFLAGS } { 171 append GDBFLAGS " -ex \"set non-stop on\"" 172 clean_restart $binfile 173 } 174 175 gdb_test_no_output "set displaced-stepping $displaced" 176 177 if ![runto all_started] { 178 fail "couldn't run to all_started" 179 return 180 } 181 set break_line [gdb_get_line_number "set breakpoint here"] 182 183 gdb_test "break $break_line if always_zero" "Breakpoint .*" "set breakpoint" 184 185 enable_debug 1 186 187 for {set iter 0} {$iter < 20} {incr iter} { 188 with_test_prefix "iter=$iter" { 189 # Return early if some test fails, to avoid cascading 190 # timeouts if something goes wrong. 191 if {[test_one_iteration] != 0} { 192 return 193 } 194 } 195 } 196} 197 198foreach_with_prefix displaced-stepping {"on" "off"} { 199 if { ${displaced-stepping} != "off" && ![support_displaced_stepping] } { 200 continue 201 } 202 203 testdriver ${displaced-stepping} 204} 205