1# This testcase is part of GDB, the GNU debugger. 2 3# Copyright 2020-2023 Free Software Foundation, Inc. 4 5# This program is free software; you can redistribute it and/or modify 6# it under the terms of the GNU General Public License as published by 7# the Free Software Foundation; either version 3 of the License, or 8# (at your option) any later version. 9# 10# This program is distributed in the hope that it will be useful, 11# but WITHOUT ANY WARRANTY; without even the implied warranty of 12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13# GNU General Public License for more details. 14# 15# You should have received a copy of the GNU General Public License 16# along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18# Test receiving TARGET_WAITKIND_EXITED events from multiple 19# inferiors. In all stop-mode, upon receiving the exit event from one 20# of the inferiors, GDB will try to stop the other inferior, too. So, 21# a stop request will be sent. Receiving a TARGET_WAITKIND_EXITED 22# status kind as a response to that stop request instead of a 23# TARGET_WAITKIND_STOPPED should be handled by GDB without problems. 24 25standard_testfile 26 27if {[use_gdb_stub]} { 28 return 0 29} 30 31if {[build_executable "failed to prepare" $testfile $srcfile]} { 32 return -1 33} 34 35# We are testing GDB's ability to stop all threads. 36# Hence, go with the all-stop-on-top-of-non-stop mode. 37save_vars { GDBFLAGS } { 38 append GDBFLAGS " -ex \"maint set target-non-stop on\"" 39 clean_restart ${binfile} 40} 41 42# Start inferior NUM. 43 44proc start_inferior {num} { 45 with_test_prefix "start_inferior $num" { 46 global srcfile binfile 47 48 if {$num != 1} { 49 gdb_test "add-inferior" "Added inferior $num.*" \ 50 "add empty inferior" 51 gdb_test "inferior $num" "Switching to inferior $num.*" \ 52 "switch to inferior" 53 } 54 55 gdb_load $binfile 56 57 if {[gdb_start_cmd] < 0} { 58 fail "could not start" 59 return -1 60 } 61 gdb_test "" ".*reakpoint .*, main .*${srcfile}.*" "start" 62 } 63 64 return 0 65} 66 67# Sufficient inferiors to make sure that at least some other inferior 68# exits while we're handling a process exit event. 69set NUM_INFS 10 70 71for {set i 1} {$i <= $NUM_INFS} {incr i} { 72 if {[start_inferior $i] < 0} { 73 return -1 74 } 75} 76 77# We want to continue all processes. 78gdb_test_no_output "set schedule-multiple on" 79 80# Check that "continue" continues to the end of an inferior, as many 81# times as we have inferiors. 82 83for {set i 1} {$i <= $NUM_INFS} {incr i} { 84 with_test_prefix "inf $i" { 85 set live_inferior "" 86 87 # Pick any live inferior. 88 gdb_test_multiple "info inferiors" "" { 89 -re "($decimal) *process.*$gdb_prompt $" { 90 set live_inferior $expect_out(1,string) 91 } 92 } 93 94 if {$live_inferior == ""} { 95 return -1 96 } 97 98 gdb_test "inferior $live_inferior" \ 99 ".*Switching to inferior $live_inferior.*" \ 100 "switch to another inferior" 101 102 set exited_inferior "" 103 104 # We want GDB to complete the command and return the prompt 105 # instead of going into an infinite loop. 106 gdb_test_multiple "continue" "continue" { 107 -re "Inferior ($decimal) \[^\n\r\]+ exited normally.*$gdb_prompt $" { 108 set exited_inferior $expect_out(1,string) 109 pass $gdb_test_name 110 } 111 } 112 113 if {$exited_inferior == ""} { 114 return -1 115 } 116 } 117} 118 119# Finally, check that we can re-run all inferiors. Note that if any 120# inferior was still alive this would catch it, as "run" would query 121# "Start it from the beginning?". 122 123delete_breakpoints 124 125for {set i 1} {$i <= $NUM_INFS} {incr i} { 126 with_test_prefix "inf $i" { 127 gdb_test "inferior $i" \ 128 ".*Switching to inferior $i.*" \ 129 "switch to inferior for re-run" 130 131 gdb_test "run" "$inferior_exited_re normally\]" \ 132 "re-run inferior" 133 } 134} 135