]> Git Repo - binutils.git/blob - gdb/testsuite/gdb.threads/pthreads.exp
Automatic date update in version.in
[binutils.git] / gdb / testsuite / gdb.threads / pthreads.exp
1 # Copyright (C) 1996-2022 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 # This file was written by Fred Fish. ([email protected])
17
18 # This test requires sending ^C to interrupt the running target.
19 if [target_info exists gdb,nointerrupts] {
20     verbose "Skipping pthreads.exp because of nointerrupts."
21     return
22 }
23
24 standard_testfile
25
26 # regexp for "horizontal" text (i.e. doesn't include newline or
27 # carriage return)
28 set horiz "\[^\n\r\]*"
29
30 if {[istarget "*-*-linux"]} {
31     set target_cflags "-D_MIT_POSIX_THREADS"
32 } else {
33     set target_cflags ""
34 }
35
36 if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable debug] != "" } {
37     return -1
38 }
39
40 clean_restart ${binfile}
41
42 gdb_test_no_output "set print sevenbit-strings"
43 #gdb_test_no_output "set print address off"
44 gdb_test_no_output "set width 0"
45
46 # We'll need this when we send_gdb a ^C to GDB.  Need to do it before we
47 # run the program and gdb starts saving and restoring tty states.
48 gdb_test "shell stty intr '^C'" ".*"
49
50 proc all_threads_running {} {
51     global gdb_prompt
52     global srcfile
53
54     # Reset all the counters to zero.
55     gdb_test_no_output "set var common_routine::hits=0"
56     gdb_test_no_output "set var common_routine::from_thread1=0"
57     gdb_test_no_output "set var common_routine::from_thread2=0"
58     gdb_test_no_output "set var common_routine::from_main=0"
59     gdb_test_no_output "set var common_routine::full_coverage=0"
60
61     # Disable all breakpoints.
62     gdb_test_no_output "disable"
63
64     # Set up a breakpoint that will cause us to stop when we have
65     # been called 15 times.  This should be plenty of time to allow
66     # every thread to run at least once, since each thread sleeps for
67     # one second between calls to common_routine.
68     gdb_test "tbreak common_routine if hits >= 15" ".*"
69
70     # Start all the threads running again and wait for the inferior
71     # to stop.  Since no other breakpoints are set at this time
72     # we should stop only when we have been previously called 15 times.
73
74     set return_me 1
75
76     gdb_test_multiple "continue" "continue until common routine run 15 times" {
77         -re "Continuing.*common_routine.*at.*$srcfile.*$gdb_prompt $" {
78             set return_me 0
79         }
80     }
81
82     if {$return_me == 1} {
83         return 0
84     }
85
86     # Check that we stopped when we actually expected to stop, by
87     # verifying that there have been 15 previous hits.
88
89     # NOTE: Because of synchronization behavior, it is possible for
90     # more than one thread to increment "hits" between one breakpoint
91     # trap and the next.  So stopping after 16 or 17 hits should be
92     # considered acceptable.
93
94     gdb_test_multiple "p common_routine::hits" \
95         "stopped before calling common_routine 15 times" {
96             -re ".*= 15\r\n$gdb_prompt $" {
97                 pass "stopped before calling common_routine 15 times"
98             }
99             -re ".*= 16\r\n$gdb_prompt $" {
100                 pass "stopped before calling common_routine 15 times (16 times)"
101             }
102             -re ".*= 17\r\n$gdb_prompt $" {
103                 pass "stopped before calling common_routine 15 times (17 times)"
104             }
105         }
106
107     # Also check that all of the threads have run, which will only be true
108     # if the full_coverage variable is set.
109
110     set return_me 1
111     gdb_test_multiple "p common_routine::full_coverage" \
112         "some threads didn't run" {
113             -re ".* = 1.*$gdb_prompt $" {
114             }
115             -re ".* = 0.*$gdb_prompt $" {
116                 fail "some threads didn't run"
117                 set return_me 0
118             }
119         }
120
121     # Looks fine, return success.
122     return $return_me
123 }
124
125 proc test_startup {} {
126     global srcdir srcfile gdb_prompt expect_out
127     global horiz
128     global main_id thread1_id thread2_id
129
130     # We should be able to do an info threads before starting any others.
131     set return_me 1
132     gdb_test_multiple "info threads" "info threads" {
133         -re ".*Thread.*main.*$gdb_prompt $" {
134             pass "info threads"
135             set return_me 0
136         }
137         -re "\r\n$gdb_prompt $" {
138             unsupported "gdb does not support pthreads for this machine"
139         }
140     }
141
142     if {$return_me == 1} {
143         return 0
144     }
145
146     # Extract the thread id number of main thread from "info threads" output.
147     gdb_test_multiple "info threads" "get main thread id" {
148         -re "(\[0-9\]+)(${horiz}Thread${horiz}main.*)($gdb_prompt $)" {
149         }
150     }
151
152     set main_id $expect_out(1,string)
153
154     # Check that we can continue and create the first thread.
155     gdb_test "break thread1" "Breakpoint .* file .*$srcfile.*"
156     gdb_test "continue" \
157             "Continuing.*Breakpoint .*, thread1 \\(arg=0xfeedface\\).*at.*$srcfile.*" \
158             "Continue to creation of first thread"
159     gdb_test_no_output "disable"
160
161     # Extract the thread id number of thread 1 from "info threads" output.
162     gdb_test_multiple "info threads" "get thread 1 id" {
163         -re "(\[0-9\]+)(${horiz}Thread${horiz}thread1.*)($gdb_prompt $)" {
164         }
165     }
166
167     set thread1_id $expect_out(1,string)
168
169     # Check that we can continue and create the second thread,
170     # ignoring the first thread for the moment.
171     gdb_test "break thread2" "Breakpoint .* file .*$srcfile.*"
172     gdb_test "continue" \
173             "Continuing.*Breakpoint .*, thread2 \\(arg=0xdeadbeef\\).*at.*$srcfile.*" \
174             "continue to creation of second thread"
175
176     # Extract the thread id number of thread 2 from "info threads" output.
177     gdb_test_multiple "info threads" "get thread 2 id" {
178         -re "(\[0-9\]+)(${horiz}Thread${horiz}thread2.*)($gdb_prompt $)" {
179         }
180     }
181
182     set thread2_id $expect_out(1,string)
183
184     return 1
185 }
186
187 proc check_control_c {} {
188     global gdb_prompt
189
190     # Verify that all threads are running.
191     with_test_prefix "after startup" {
192         if {[all_threads_running]} {
193             pass "all threads running after startup"
194         }
195     }
196
197     # Send a continue followed by ^C to the process to stop it.
198     gdb_test_multiple "continue" "continue with all threads running" {
199         -re "Continuing." {
200             pass "continue with all threads running"
201         }
202     }
203     after 2000
204     send_gdb "\003"
205     set description "Stopped with a ^C"
206     gdb_expect {
207         -re "Thread .* received signal SIGINT.*$gdb_prompt $" {
208             pass $description
209         }
210         -re "Quit.*$gdb_prompt $" {
211             pass $description
212         }
213         timeout {
214             fail "$description (timeout)"
215             return 1
216         }
217     }
218     gdb_test "bt" ".*"
219
220     # Verify that all threads can be run again after a ^C stop.
221     with_test_prefix "after continue" {
222         if {[all_threads_running]} {
223             pass "all threads running after continuing from ^C stop"
224         }
225     }
226     return 0
227 }
228
229 proc check_backtraces {} {
230     global gdb_prompt main_id thread1_id thread2_id
231
232     # Check that the "thread apply N backtrace" command works
233
234     gdb_test "thread apply $main_id backtrace" \
235             ".* in main \\(argc=.*, argv=.*\\).*" \
236             "check backtrace from main thread"
237     gdb_test "thread apply $thread1_id backtrace" \
238             ".* in thread1 \\(arg=0xfeedface\\).*" \
239             "check backtrace from thread 1"
240     gdb_test "thread apply $thread2_id backtrace" \
241             ".* in thread2 \\(arg=0xdeadbeef\\).*" \
242             "check backtrace from thread 2"
243
244     # Check that we can apply the backtrace command to all
245     # three threads with a single gdb command
246
247     gdb_test "thread apply $main_id $thread1_id $thread2_id bt" \
248             ".* in main .* in thread1 .* in thread2.*" \
249             "apply backtrace command to all three threads"
250
251     # Check that we can do thread specific backtraces
252     # This also tests that we can do thread specific breakpoints.
253
254     gdb_test "break common_routine thread $thread2_id" \
255             "Breakpoint .* at 0x.* file .* line .*" \
256             "set break at common_routine in thread 2"
257
258     gdb_test_multiple "continue" "continue to bkpt at common_routine in thread 2" {
259         -re "Breakpoint .* common_routine \\(arg=2\\).*$gdb_prompt $" {
260             pass "continue to bkpt at common_routine in thread 2"
261             gdb_test "backtrace" \
262                 "#0.*common_routine \\(arg=2\\).*#1.*thread2.*" \
263                 "backtrace from thread 2 bkpt in common_routine"
264         }
265         -re "Breakpoint .* common_routine \\(arg=0\\).*$gdb_prompt $" {
266             fail "continue to bkpt at common_routine in thread 2 (arg=0)"
267         }
268         -re "Breakpoint .* common_routine \\(arg=1\\).*$gdb_prompt $" {
269             fail "continue to bkpt at common_routine in thread 2 (arg=1)"
270         }
271     }
272 }
273
274 proc check_qcs {} {
275     set any "\[^\r\n\]*"
276     set ws "\[ \t\]\+"
277     set number "\[0-9]\+"
278
279     # Check -c (continue) and -s (silently continue) flags.
280     gdb_test "thread apply 2-3 p notfound" \
281         [multi_line \
282              "" \
283              "Thread 2 ${any}" \
284              "No symbol \\\"notfound\\\" in current context." \
285             ] \
286         "run a failing command that aborts thread apply"
287
288     gdb_test "thread apply 2-3 -c p notfound" \
289         [multi_line \
290              "" \
291              "Thread 2 ${any}" \
292              "No symbol \\\"notfound\\\" in current context." \
293              "" \
294              "Thread 3 ${any}" \
295              "No symbol \\\"notfound\\\" in current context." \
296             ] \
297         "run a failing command, -c to continue"
298
299     with_test_prefix "silent flag" {
300         foreach_with_prefix cmd_and_args {
301             "thread apply all -s frame apply all -s"
302             "tfaas"
303             "taas faas"} {
304                 set cmd "$cmd_and_args p i"
305                 gdb_test $cmd \
306                     [multi_line \
307                          "" \
308                          "Thread 3 ${any}" \
309                          "#${number}${ws}${any} in thread2 ${any}" \
310                          "\\\$\[0-9]+ = ${number}${any}" \
311                          "" \
312                          "Thread 2 ${any}" \
313                          "#${number}${ws}${any} in thread1 ${any}" \
314                          "\\\$\[0-9]+ = ${number}${any}" \
315                         ] \
316                     "run a failing command except in one frame of thread 2,3, -s to silently continue"
317             }
318     }
319
320     # Check quietness.
321     gdb_test "thread apply all -s -q frame apply all -s p i" \
322         [multi_line \
323              "#${number}${ws}${any} in thread2 ${any}" \
324              "\\\$\[0-9]+ = ${number}${any}" \
325              "#${number}${ws}${any} in thread1 ${any}" \
326              "\\\$\[0-9]+ = ${number}${any}" \
327             ] \
328         "run a failing command except in one frame of thread 2,3, -s to silently continue.  Do not show thread information"
329
330     gdb_test "thread apply all -s -q frame apply all -s -q p i" \
331         [multi_line \
332              "\\\$\[0-9]+ = ${number}${any}" \
333              "\\\$\[0-9]+ = ${number}${any}" \
334             ] \
335         "run a failing command except in one frame of thread 2,3, -s to silently continue.  Do not show thread and frame info"
336
337     # Check invalid flag combinations and errors.
338     gdb_test "thread apply all -c -s p 1" \
339         "thread apply all: -c and -s are mutually exclusive" \
340         "check -c and -s cannot be used simultaneously"
341     gdb_test "taas" "Please specify a command to apply on all threads" \
342         "missing command for taas"
343     gdb_test "tfaas" "Please specify a command to apply on all frames of all threads" \
344         "missing command for tfaas"
345
346 }
347
348 if {[runto_main]} {
349     if {[test_startup]} {
350         if {[check_control_c]} {
351             warning "Could not stop child with ^C; skipping rest of tests.\n"
352             return
353         }
354         check_backtraces
355         check_qcs
356     }
357 }
This page took 0.04657 seconds and 4 git commands to generate.