1# Copyright 2022-2023 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# In the past we would use glibc's buffered input for the mi tty. 17# This buffering would cause problems if two commands are sent to gdb 18# in a single write call, and, if the first command (excluding its 19# trailing newline) exactly filled glibc's internal buffer. 20# 21# The solution to this problem was to stop using glibc's buffering for 22# the mi tty. 23# 24# To test for this situation we send two command to gdb in a loop, the 25# first command gets progressively bigger. We check that gdb 26# correctly sees both commands. 27 28load_lib mi-support.exp 29set MIFLAGS "-i=mi" 30 31# Start gdb, passing ARGS to mi_gdb_start. Then run a series of tests 32# passing two commands to gdb in a single write action. The first 33# command is increasingly long, while the second command stays very 34# short. 35# 36# Check that gdb sees, and performs, both commands. 37proc run_test { args } { 38 global mi_gdb_prompt 39 global decimal 40 41 gdb_exit 42 if [mi_gdb_start $args] { 43 return 44 } 45 46 set start 1 47 set limit 2049 48 49 mi_gdb_test "set \$a = \"FIRST COMMAND\"" ".*" 50 mi_gdb_test "set \$b = \"TEST COMPLETE\"" ".*" 51 52 for { set i $start } { $i < $limit } { incr i } { 53 54 set cmd "" 55 56 # Create a command that is at least `i` characters long. 57 set first_cmd "-data-evaluate-expression \$a" 58 while { [string length $first_cmd] < $i } { 59 set first_cmd " $first_cmd" 60 } 61 62 # We reset `i`, our loop counter, here. When i is large this 63 # should be a nop as we attempt to make the first command 64 # length be i above. However, the first time around the loop 65 # we start with an i value of 1, however, we can't make a 66 # command that short, so, by resetting i here we effectively 67 # skip the first couple of loop iterations where i is less 68 # than the minimum command length. 69 set i [string length $first_cmd] 70 verbose -log "length of first command is $i" 71 72 set cmd "${first_cmd}\n-data-evaluate-expression \$b\n" 73 74 # We need to call send_gdb ourselves here as gdb_test_multiple 75 # will try to send each line of the command separately (breaking 76 # the command at newline characters). This splitting will more 77 # than likely mean that gdb will see and process the first command 78 # before the second command arrives, this prevents the bug from 79 # triggering. 80 send_gdb "$cmd" 81 82 # Now check for output from the two commands. We do this 83 # using two calls to gdb_test_multiple, this is because the 84 # echoing of the second command can sometime get mixed 85 # unexpectedly with the command output, this is especially 86 # likely when running using the read1 technique. 87 # 88 # When using a single gdb_test_multiple we need to anchor 89 # patterns using a ^, however, this requires us to consume and 90 # discard all lines that are not part of the output that we're 91 # looking for. However, due to the unpredictable 92 # intermingling, it's much easier if we drop the ^ anchor. 93 # However, with this gone dejagnu would sometimes match the 94 # second comand output before the first commands output. 95 # 96 # This approach just looks for the first command output, then, 97 # once that has been found, we start looking for the second 98 # command output, this seems pretty reliable. 99 set seen_first_message false 100 set seen_second_message false 101 102 gdb_test_multiple "" "look for first command output, command length $i" -prompt "$mi_gdb_prompt" { 103 -re "\\^done.*,value=\"\\\\\"FIRST COMMAND\\\\\"\"" { 104 set seen_first_message true 105 exp_continue 106 } 107 -re "\r\n$mi_gdb_prompt" { 108 gdb_assert $seen_first_message $gdb_test_name 109 } 110 } 111 112 gdb_test_multiple "" "look for second command output, command length $i" -prompt "$mi_gdb_prompt" { 113 -re "\\^done,value=\"\\\\\"TEST COMPLETE\\\\\"\"\r\n$mi_gdb_prompt" { 114 pass $gdb_test_name 115 set seen_second_message true 116 } 117 } 118 119 # If one of the above tests failed then lets no waste our time 120 # checking different command lengths. The actual bug this 121 # test checks for would result in a timeout, so we don't want 122 # to risk lots more timeouts. 123 if { ! [expr $seen_first_message && $seen_second_message ] } { 124 break 125 } 126 } 127} 128 129foreach_with_prefix args { "" "separate-mi-tty" } { 130 run_test $args 131} 132