1# Copyright (C) 2017-2019 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# Test quitting GDB with live inferiors. 17# 18# Exercises combinations of: 19# 20# - quitting with "quit" command, or with SIGTERM/SIGHUP signals. 21# 22# - quitting with live inferior selected, or file_stratum inferior 23# selected. 24# 25# - quitting after "run", or after "attach". 26# 27# - quitting with local executable, or executable loaded from target 28# directly (via default "target:/" sysroot), or with no executable 29# loaded. 30 31# Note: sending an asynchronous SIGHUP with kill is not the exact same 32# as closing GDB's input, and that resulting in SIGHUP. However, it's 33# still a good approximation, and it has the advantage that because 34# GDB still has a terminal, internal errors (if any) are visible in 35# gdb.sum/gdb.log. 36 37standard_testfile 38 39if {[build_executable "failed to build" $testfile $srcfile debug]} { 40 return 41} 42 43# Send signal SIG to GDB, and expect GDB to exit. 44 45proc test_quit_with_sig {sig} { 46 set gdb_pid [exp_pid -i [board_info host fileid]] 47 remote_exec host "kill -$sig ${gdb_pid}" 48 49 set test "quit with SIG$sig" 50 # If GDB mishandles the signal and doesn't exit, this should FAIL 51 # with timeout. We don't expect a GDB prompt, so if we see one, 52 # we'll FAIL too (without having to wait for timeout). 53 gdb_test_multiple "" $test { 54 eof { 55 pass $test 56 } 57 } 58} 59 60# Call the "quit" command with an inferior live. 61# 62# APPEAR_HOW specifies how the running inferior appears in GDB. Can 63# be either: 64# 65# - "run" 66# 67# Appear via the "run" command. 68# 69# - "attach" 70# 71# Appear via the "attach" command. 72# 73# - "attach-nofile" 74# 75# Appear via the "attach" command, but with no program preloaded in 76# GDB so that GDB reads the program directly from the target when 77# remote debugging (i.e., from the target:/ sysroot). This makes 78# sure that GDB doesn't misbehave if it decides to close the 79# 'target:/.../program' exec_file after closing the remote 80# connection. 81# 82# EXTRA_INFERIOR is a boolean that specifies whether we try to quit 83# GDB with an extra executable-only (before "run") inferior selected 84# or whether we try to quit GDB when the live inferior is selected, 85# with no extra inferior. 86# 87# QUIT_HOW specifies how to tell GDB to quit. It can be either "quit" 88# (for "quit" command), "sighup" or "sigterm" (for quitting with 89# SIGHUP and SIGTERM signals, respectively). 90 91proc quit_with_live_inferior {appear_how extra_inferior quit_how} { 92 global srcfile testfile binfile 93 global gdb_spawn_id gdb_prompt 94 95 set test_spawn_id "" 96 97 if {$appear_how != "attach-nofile"} { 98 clean_restart $binfile 99 } else { 100 clean_restart 101 } 102 103 if {$appear_how == "run"} { 104 if ![runto_main] then { 105 fail "can't run to main" 106 return 107 } 108 } elseif {$appear_how == "attach" || $appear_how == "attach-nofile"} { 109 set test_spawn_id [spawn_wait_for_attach $binfile] 110 set testpid [spawn_id_get_pid $test_spawn_id] 111 112 if {[gdb_test "attach $testpid" \ 113 "Attaching to .*process $testpid.*Reading symbols from.*" \ 114 "attach"] != 0} { 115 kill_wait_spawned_process $test_spawn_id 116 return 117 } 118 } else { 119 error "unhandled '\$appear_how': $appear_how" 120 } 121 122 if {$extra_inferior} { 123 gdb_test "add-inferior" "Added inferior 2*" \ 124 "add empty inferior 2" 125 gdb_test "inferior 2" "Switching to inferior 2.*" \ 126 "switch to inferior 2" 127 } 128 129 if {$quit_how == "quit"} { 130 # Make regexp that matches the "quit" command's output. 131 proc make_re {how} { 132 multi_line \ 133 "A debugging session is active.\[ \t\r\n\]*Inferior 1\[^\r\n\]* will be $how\." \ 134 "" \ 135 "Quit anyway\\? \\(y or n\\) $" 136 } 137 138 if {$appear_how == "run"} { 139 set quit_anyway_re [make_re "killed"] 140 } else { 141 set quit_anyway_re [make_re "detached"] 142 } 143 144 set test "quit with \"quit\"" 145 gdb_test_multiple "quit" $test { 146 -re $quit_anyway_re { 147 send_gdb "y\n" 148 gdb_test_multiple "" $test { 149 eof { 150 pass $test 151 } 152 } 153 } 154 } 155 } elseif {$quit_how == "sighup"} { 156 test_quit_with_sig HUP 157 } elseif {$quit_how == "sigterm"} { 158 test_quit_with_sig TERM 159 } else { 160 error "unhandled '\$quit_how': $quit_how" 161 } 162 163 if {$test_spawn_id != ""} { 164 kill_wait_spawned_process $test_spawn_id 165 } 166} 167 168foreach_with_prefix appear_how {"run" "attach" "attach-nofile"} { 169 if {$appear_how != "run" && ![can_spawn_for_attach]} { 170 continue 171 } 172 173 foreach_with_prefix extra_inferior {0 1} { 174 foreach_with_prefix quit_how {"quit" "sigterm" "sighup"} { 175 quit_with_live_inferior $appear_how $extra_inferior $quit_how 176 } 177 } 178} 179