xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/testsuite/gdb.threads/break-while-running.exp (revision 8b657b0747480f8989760d71343d6dd33f8d4cf9)
1# Copyright (C) 2014-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# Test that:
17#
18# - setting a breakpoint while a thread is running results in the
19#   breakpoint being inserted immediately.
20#
21# - if breakpoint always-inserted mode is off, GDB doesn't remove
22#   breakpoints from the target when a thread stops, if there are
23#   still threads running.
24
25standard_testfile
26
27if {[build_executable "failed to prepare" $testfile $srcfile {debug pthreads}] == -1} {
28    return -1
29}
30
31# The test proper.  UPDATE_THREAD_LIST indicates whether we should do
32# an "info threads" to sync the thread list after the first stop.
33# ALWAYS_INSERTED indicates whether testing in "breakpoint
34# always-inserted" mode.  NON_STOP indicates whether we're testing in
35# non-stop, or all-stop mode.
36
37proc test { update_thread_list always_inserted non_stop } {
38    global srcfile binfile
39    global gdb_prompt
40    global decimal
41
42    clean_restart $binfile
43
44    gdb_test_no_output "set non-stop $non_stop"
45    gdb_test_no_output "set breakpoint always-inserted $always_inserted"
46
47    if ![runto_main] {
48	return -1
49    }
50
51    # In all-stop, check whether we're testing with the remote or
52    # extended-remote targets.  If so, skip the tests, as with the
53    # RSP, we can't issue commands until the target replies to vCont.
54    # Not an issue with the non-stop RSP variant, which has a
55    # non-blocking vCont.
56    if {$non_stop=="off" && [gdb_is_target_remote]} {
57	return -1
58    }
59
60    gdb_breakpoint [gdb_get_line_number "set wait-thread breakpoint here"]
61    gdb_continue_to_breakpoint "run to wait-thread breakpoint"
62
63    delete_breakpoints
64
65    # Leave the main thread stopped, so GDB can poke at memory freely.
66    if {$non_stop == "off"} {
67	gdb_test_no_output "set scheduler-locking on"
68	gdb_test "thread 2" "Switching to .*"
69	gdb_test "continue &" "Continuing\." "continuing thread 2"
70	gdb_test "thread 3" "Switching to .*"
71	gdb_test "continue &" "Continuing\." "continuing thread 3"
72	gdb_test "thread 1" "Switching to .*" "switch back to main thread"
73    }
74
75    # Test with and without pulling the thread list explicitly with
76    # "info threads".  GDB should be able to figure out itself whether
77    # the target is running and thus breakpoints should be inserted,
78    # without the user explicitly fetching the thread list.
79    if {$update_thread_list} {
80	gdb_test "info threads" \
81	    "main .*\\\(running\\\).*\\\(running\\\).*" \
82	    "only main stopped"
83    }
84
85    # Don't use gdb_test as it's racy in this case -- gdb_test matches
86    # the prompt with an end anchor.  Sometimes expect will manage to
87    # read the breakpoint hit output while still processing this test,
88    # defeating the anchor.
89    set test "set breakpoint while a thread is running"
90    gdb_test_multiple "break breakpoint_function" $test {
91	-re "Breakpoint $decimal at .*: file .*$srcfile.*\r\n$gdb_prompt " {
92	    pass $test
93	}
94	-re "$gdb_prompt " {
95	    fail $test
96	}
97    }
98
99    # Check that the breakpoint is hit.  Can't use gdb_test here, as
100    # no prompt is expected to come out.
101    set test "breakpoint is hit"
102    gdb_test_multiple "" $test {
103	-re "Breakpoint .*, breakpoint_function \[^\r\n\]+" {
104	    pass $test
105	}
106    }
107
108    if {$non_stop == "on"} {
109	gdb_test "info threads" \
110	    "main .* breakpoint_function .*\\\(running\\\)" \
111	    "one thread running"
112
113	# Unblock the other thread, which should then trip on the same
114	# breakpoint, unless GDB removed it by mistake.  Can't use
115	# gdb_test here for the same reasons as above.
116	set test "unblock second thread"
117	gdb_test_multiple "print second_child = 1" $test {
118	    -re " = 1\r\n$gdb_prompt " {
119		pass $test
120	    }
121	    -re "$gdb_prompt " {
122		fail $test
123	    }
124	}
125
126	set test "breakpoint on second child is hit"
127	gdb_test_multiple "" $test {
128	    -re "Breakpoint .*, breakpoint_function \[^\r\n\]+" {
129		pass $test
130	    }
131	}
132
133	gdb_test "info threads" \
134	    " main .* breakpoint_function .* breakpoint_function .*" \
135	    "all threads stopped"
136    } else {
137	# This test is not merged with the non-stop one because in
138	# all-stop we don't know where the other thread stops (inside
139	# usleep, for example).
140	set test "all threads stopped"
141	gdb_test_multiple "info threads" "$test" {
142	    -re "\\\(running\\\).*$gdb_prompt $" {
143		fail $test
144	    }
145	    -re "main .* breakpoint_function .*$gdb_prompt $" {
146		pass $test
147	    }
148	}
149    }
150}
151
152foreach update_thread_list { true false } {
153    foreach always_inserted { "off" "on" } {
154	foreach non_stop { "off" "on" } {
155	    set stop_mode [expr ($non_stop=="off")?"all-stop":"non-stop"]
156	    set update_list_mode [expr ($update_thread_list)?"w/ithr":"wo/ithr"]
157	    with_test_prefix "$update_list_mode: always-inserted $always_inserted: $stop_mode" {
158		test $update_thread_list $always_inserted $non_stop
159	    }
160	}
161    }
162}
163