205 lines
4.7 KiB
Plaintext
205 lines
4.7 KiB
Plaintext
# Copyright (C) 2016-2017 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/>.
|
|
|
|
# Regression test for PR gdb/18360. Test that "interrupt -a" while
|
|
# some thread is stepping over a breakpoint behaves as expected.
|
|
|
|
standard_testfile
|
|
|
|
if {[prepare_for_testing "failed to prepare" $testfile $srcfile \
|
|
{debug pthreads}] == -1} {
|
|
return -1
|
|
}
|
|
|
|
if {![runto_main]} {
|
|
fail "can't run to main"
|
|
return -1
|
|
}
|
|
|
|
# Read the number of threads out of the inferior.
|
|
set NUM_THREADS [get_integer_valueof "num_threads" -1]
|
|
|
|
# Account for the main thread.
|
|
incr NUM_THREADS
|
|
|
|
# Run command and wait for the prompt, without end anchor.
|
|
|
|
proc gdb_test_no_anchor {cmd} {
|
|
global gdb_prompt
|
|
|
|
gdb_test_multiple $cmd $cmd {
|
|
-re "$gdb_prompt " {
|
|
pass $cmd
|
|
}
|
|
-re "infrun:" {
|
|
exp_continue
|
|
}
|
|
}
|
|
}
|
|
|
|
# Enable/disable debugging.
|
|
|
|
proc enable_debug {enable} {
|
|
|
|
# Comment out to debug problems with the test.
|
|
return
|
|
|
|
gdb_test_no_anchor "set debug infrun $enable"
|
|
gdb_test_no_anchor "set debug displaced $enable"
|
|
}
|
|
|
|
# If RESULT is not zero, make the caller return RESULT.
|
|
|
|
proc return_if_nonzero { result } {
|
|
if {$result != 0} {
|
|
return -code return $result
|
|
}
|
|
}
|
|
|
|
# Do one iteration of "c -a& -> interrupt -a". Return zero on sucess,
|
|
# and non-zero if some test fails.
|
|
|
|
proc test_one_iteration {} {
|
|
global gdb_prompt
|
|
global NUM_THREADS
|
|
global decimal
|
|
|
|
set saw_continuing 0
|
|
set test "continue -a &"
|
|
return_if_nonzero [gdb_test_multiple $test $test {
|
|
-re "Continuing.\r\n" {
|
|
set saw_continuing 1
|
|
exp_continue
|
|
}
|
|
-re "$gdb_prompt " {
|
|
if ![gdb_assert $saw_continuing $test] {
|
|
return 1
|
|
}
|
|
}
|
|
-re "infrun:" {
|
|
exp_continue
|
|
}
|
|
}]
|
|
|
|
set running_count 0
|
|
set test "all threads are running"
|
|
return_if_nonzero [gdb_test_multiple "info threads" $test {
|
|
-re "Thread \[^\r\n\]* \\(running\\)" {
|
|
incr running_count
|
|
exp_continue
|
|
}
|
|
-re "$gdb_prompt " {
|
|
if ![gdb_assert {$running_count == $NUM_THREADS} $test] {
|
|
return 1
|
|
}
|
|
}
|
|
-re "infrun:" {
|
|
exp_continue
|
|
}
|
|
}]
|
|
|
|
set test "interrupt -a"
|
|
return_if_nonzero [gdb_test_multiple $test $test {
|
|
-re "$gdb_prompt " {
|
|
pass $test
|
|
}
|
|
-re "infrun:" {
|
|
exp_continue
|
|
}
|
|
}]
|
|
|
|
set stopped_count 0
|
|
set test "wait for stops"
|
|
# Don't return on failure here, in order to let "info threads" put
|
|
# useful info in gdb.log.
|
|
gdb_test_multiple "" $test {
|
|
-re "Thread $decimal \[^\r\n\]*stopped" {
|
|
incr stopped_count
|
|
if {$stopped_count != $NUM_THREADS} {
|
|
exp_continue
|
|
}
|
|
}
|
|
-re "$gdb_prompt " {
|
|
gdb_assert {$stopped_count == $NUM_THREADS} $test
|
|
}
|
|
-re "infrun:" {
|
|
exp_continue
|
|
}
|
|
}
|
|
|
|
# Check if all threads are seen as stopped with "info
|
|
# threads". It's a bit redundant with the test above, but
|
|
# it's useful to have this in the gdb.log if the above ever
|
|
# happens to fail.
|
|
set running_count 0
|
|
set test "all threads are stopped"
|
|
return_if_nonzero [gdb_test_multiple "info threads" $test {
|
|
-re "Thread \[^\r\n\]* \\(running\\)" {
|
|
incr running_count
|
|
exp_continue
|
|
}
|
|
-re "$gdb_prompt " {
|
|
if ![gdb_assert {$running_count == 0} $test] {
|
|
return 1
|
|
}
|
|
}
|
|
}]
|
|
|
|
return 0
|
|
}
|
|
|
|
# The test driver proper. If DISPLACED is "on", turn on displaced
|
|
# stepping. If "off", turn it off.
|
|
|
|
proc testdriver {displaced} {
|
|
global binfile
|
|
global GDBFLAGS
|
|
|
|
save_vars { GDBFLAGS } {
|
|
append GDBFLAGS " -ex \"set non-stop on\""
|
|
clean_restart $binfile
|
|
}
|
|
|
|
gdb_test_no_output "set displaced-stepping $displaced"
|
|
|
|
if ![runto all_started] {
|
|
fail "couldn't run to all_started"
|
|
return
|
|
}
|
|
set break_line [gdb_get_line_number "set breakpoint here"]
|
|
|
|
gdb_test "break $break_line if always_zero" "Breakpoint .*" "set breakpoint"
|
|
|
|
enable_debug 1
|
|
|
|
for {set iter 0} {$iter < 20} {incr iter} {
|
|
with_test_prefix "iter=$iter" {
|
|
# Return early if some test fails, to avoid cascading
|
|
# timeouts if something goes wrong.
|
|
if {[test_one_iteration] != 0} {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach_with_prefix displaced-stepping {"on" "off"} {
|
|
if { ${displaced-stepping} != "off" && ![support_displaced_stepping] } {
|
|
continue
|
|
}
|
|
|
|
testdriver ${displaced-stepping}
|
|
}
|