[gdb/symtab] Fix gdb.base/fission-macro.exp with unix/-m32
[binutils-gdb.git] / gdb / testsuite / gdb.threads / infcall-from-bp-cond-timeout.exp
blob8f17f13d97a9fe485924114e91c926955378dfd8
1 # Copyright 2022-2024 Free Software Foundation, Inc.
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.
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.
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/>.
16 # Tests inferior calls executed from a breakpoint condition in
17 # a multi-threaded program.
19 # This test has the inferior function call timeout, and checks how GDB
20 # handles this situation.
22 standard_testfile
24 if { [build_executable "failed to prepare" ${binfile} "${srcfile}" \
25           {debug pthreads}] } {
26     return
29 set cond_bp_line [gdb_get_line_number "Conditional breakpoint here"]
30 set final_bp_line [gdb_get_line_number "Stop marker"]
31 set segfault_line [gdb_get_line_number "Segfault here"]
33 # Setup GDB based on TARGET_ASYNC, TARGET_NON_STOP, and NON_STOP.
34 # Setup some breakpoints in the inferior, one of which has an inferior
35 # call within its condition.
37 # Continue GDB, the breakpoint with inferior call will be hit, but the
38 # inferior call will never return.  We expect GDB to timeout.
40 # The reason that the inferior call never completes is that a second
41 # thread, on which the inferior call relies, either hits a breakpoint
42 # (when OTHER_THREAD_BP is true), or crashes (when OTHER_THREAD_BP is
43 # false).
45 # When UNWIND is "on" GDB will unwind the thread which performed the
46 # inferior function call back to the state where the inferior call was
47 # made (when the inferior call times out).  Otherwise, when UNWIND is
48 # "off", the inferior is left in the frame where the timeout occurred.
49 proc run_test { target_async target_non_stop non_stop other_thread_bp unwind } {
50     save_vars { ::GDBFLAGS } {
51         append ::GDBFLAGS " -ex \"maint set target-non-stop $target_non_stop\""
52         append ::GDBFLAGS " -ex \"maint non-stop $non_stop\""
53         append ::GDBFLAGS " -ex \"maintenance set target-async ${target_async}\""
55         clean_restart ${::binfile}
56     }
58     if {![runto_main]} {
59         return
60     }
62     # The default timeout for indirect inferior calls (e.g. inferior
63     # calls for conditional breakpoint expressions) is pretty high.
64     # We don't want the test to take too long, so reduce this.
65     #
66     # However, the test relies on a second thread hitting some event
67     # (either a breakpoint or signal) before this timeout expires.
68     #
69     # There is a chance that on a really slow system this might not
70     # happen, in which case the test might fail.
71     #
72     # However, we still allocate 5 seconds, which feels like it should
73     # be enough time in most cases, but maybe we need to do something
74     # smarter here?  Possibly we could have some initial run where the
75     # inferior doesn't timeout, but does perform the same interaction
76     # between threads, we could time that, and use that as the basis
77     # for this timeout.  For now though, we just hope 5 seconds is
78     # enough.
79     gdb_test_no_output "set indirect-call-timeout 5"
80     gdb_test_no_output "set unwind-on-timeout $unwind"
82     gdb_breakpoint \
83         "${::srcfile}:${::cond_bp_line} if (condition_func ())"
84     set bp_num [get_integer_valueof "\$bpnum" "*UNKNOWN*" \
85                     "get number for conditional breakpoint"]
87     gdb_breakpoint "${::srcfile}:${::final_bp_line}"
88     set final_bp_num [get_integer_valueof "\$bpnum" "*UNKNOWN*" \
89                           "get number for final breakpoint"]
91     # The thread performing an inferior call relies on a second
92     # thread.  The second thread will segfault unless it hits a
93     # breakpoint first.  In either case the initial thread will not
94     # complete its inferior call.
95     if { $other_thread_bp } {
96         gdb_breakpoint "${::srcfile}:${::segfault_line}"
97         set segfault_bp_num [get_integer_valueof "\$bpnum" "*UNKNOWN*" \
98                                  "get number for segfault breakpoint"]
99     }
101     if { $unwind } {
102         gdb_test "continue" \
103             [multi_line \
104                  "Error in testing condition for breakpoint ${bp_num}:" \
105                  "The program being debugged timed out while in a function called from GDB\\." \
106                  "GDB has restored the context to what it was before the call\\." \
107                  "To change this behavior use \"set unwind-on-timeout off\"\\." \
108                  "Evaluation of the expression containing the function" \
109                  "\\(condition_func\\) will be abandoned\\." \
110                  "" \
111                  "Thread ${::decimal}\[^\r\n\]*hit Breakpoint ${bp_num}, \[^\r\n\]+" \
112                  "\[^\r\n\]+ Conditional breakpoint here\\. \[^\r\n\]+"] \
113             "expected timeout waiting for inferior call to complete"
114     } else {
115         # When non-stop mode is off we get slightly different output from GDB.
116         if { ([target_info gdb_protocol] == "remote"
117               || [target_info gdb_protocol] == "extended-remote")
118              && !$target_non_stop} {
119             set stopped_line_pattern \
120                 "Thread ${::decimal} \"\[^\r\n\"\]+\" received signal SIGINT, Interrupt\\."
121         } else {
122             set stopped_line_pattern "Thread ${::decimal} \"\[^\r\n\"\]+\" stopped\\."
123         }
125         gdb_test "continue" \
126             [multi_line \
127                  "$stopped_line_pattern" \
128                  ".*" \
129                  "Error in testing condition for breakpoint ${bp_num}:" \
130                  "The program being debugged timed out while in a function called from GDB\\." \
131                  "GDB remains in the frame where the timeout occurred\\." \
132                  "To change this behavior use \"set unwind-on-timeout on\"\\." \
133                  "Evaluation of the expression containing the function" \
134                  "\\(condition_func\\) will be abandoned\\." \
135                  "When the function is done executing, GDB will silently stop\\."] \
136             "expected timeout waiting for inferior call to complete"
137     }
139     # Remember that other thread that either crashed (with a segfault)
140     # or hit a breakpoint?  Now that the inferior call has timed out,
141     # if we try to resume then we should see the pending event from
142     # that other thread.
143     if { $other_thread_bp } {
144         gdb_test "continue" \
145             [multi_line \
146                  "Continuing\\." \
147                  ".*" \
148                  "" \
149                  "Thread ${::decimal} \"\[^\"\r\n\]+\" hit Breakpoint ${segfault_bp_num}, do_segfault \[^\r\n\]+:${::segfault_line}" \
150                  "${::decimal}\\s+\[^\r\n\]+Segfault here\[^\r\n\]+"] \
151             "hit the segfault breakpoint"
152     } else {
153         gdb_test "continue" \
154             [multi_line \
155                  "Continuing\\." \
156                  ".*" \
157                  "Thread ${::decimal} \"infcall-from-bp\" received signal SIGSEGV, Segmentation fault\\." \
158                  "\\\[Switching to Thread \[^\r\n\]+\\\]" \
159                  "${::hex} in do_segfault \\(\\) at \[^\r\n\]+:${::segfault_line}" \
160                  "${::decimal}\\s+\[^\r\n\]+Segfault here\[^\r\n\]+"] \
161             "hit the segfault"
162     }
165 foreach_with_prefix target_async {"on" "off" } {
167     if { !$target_async } {
168         # GDB can't timeout while waiting for a thread if the target
169         # runs with async-mode turned off; once the target is running
170         # GDB is effectively blocked until the target stops for some
171         # reason.
172         continue
173     }
175     foreach_with_prefix target_non_stop {"off" "on"} {
176         foreach_with_prefix non_stop {"off" "on"} {
177             if { $non_stop && !$target_non_stop } {
178                 # It doesn't make sense to operate GDB in non-stop
179                 # mode when the target has (in theory) non-stop mode
180                 # disabled.
181                 continue
182             }
183             foreach_with_prefix unwind {"off" "on"} {
184                 foreach_with_prefix other_thread_bp { true false } {
185                     run_test $target_async $target_non_stop $non_stop \
186                         $other_thread_bp $unwind
187                 }
188             }
189         }
190     }