Commit | Line | Data |
---|---|---|
88b9d363 | 1 | # Copyright 2021-2022 Free Software Foundation, Inc. |
92234eb1 PA |
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 attaching to a multi-threaded process, in all combinations of: | |
17 | # | |
18 | # - set non-stop on/off | |
19 | # - maint target non-stop off/on | |
20 | # - "attach" vs "attach &" | |
21 | ||
22 | if {![can_spawn_for_attach]} { | |
23 | return 0 | |
24 | } | |
25 | ||
26 | standard_testfile | |
27 | ||
28 | # The test proper. See description above. | |
29 | ||
30 | proc test {target_non_stop non_stop cmd} { | |
31 | global binfile srcfile | |
32 | global gdb_prompt | |
33 | global decimal | |
34 | global GDBFLAGS | |
35 | ||
36 | # Number of threads started by the program. | |
37 | set n_threads 10 | |
38 | ||
39 | save_vars { GDBFLAGS } { | |
40 | append GDBFLAGS " -ex \"maint set target-non-stop $target_non_stop\"" | |
41 | append GDBFLAGS " -ex \"set non-stop $non_stop\"" | |
42 | clean_restart $binfile | |
43 | } | |
44 | ||
45 | set test_spawn_id [spawn_wait_for_attach $binfile] | |
46 | set testpid [spawn_id_get_pid $test_spawn_id] | |
47 | ||
48 | set attached 0 | |
49 | set test "attach" | |
50 | set any "\[^\r\n\]*" | |
51 | ||
52 | if {$cmd == "attach"} { | |
53 | gdb_test_multiple "attach $testpid" $test { | |
54 | -re "Attaching to program:${any}process $testpid\r\n.*$gdb_prompt " { | |
55 | pass $test | |
56 | set attached 1 | |
57 | } | |
58 | } | |
59 | ||
60 | if {!$attached} { | |
61 | kill_wait_spawned_process $test_spawn_id | |
62 | return | |
63 | } | |
64 | ||
65 | if {$non_stop} { | |
66 | # In non-stop, we will see one stop per thread after | |
67 | # the prompt. | |
68 | set stops 0 | |
69 | set test "seen all stops" | |
70 | for {set thread 1} { $thread <= $n_threads } { incr thread } { | |
71 | gdb_test_multiple "" $test { | |
72 | -re "Thread $::decimal ${any} stopped" { | |
73 | incr stops | |
74 | } | |
75 | } | |
76 | } | |
77 | ||
78 | # If we haven't seen all stops, then the gdb_test_multiple | |
79 | # in the loop above will have already issued a FAIL. | |
80 | if {$stops == $n_threads} { | |
81 | pass $test | |
82 | } | |
83 | } | |
84 | ||
85 | gdb_test_multiple "info threads" "" { | |
86 | -re "\\(running\\).*$gdb_prompt $" { | |
87 | fail $gdb_test_name | |
88 | } | |
89 | -re "$gdb_prompt $" { | |
90 | pass $gdb_test_name | |
91 | } | |
92 | } | |
93 | } else { | |
94 | gdb_test_multiple "attach $testpid &" $test { | |
95 | -re "Attaching to program:${any}process $testpid\r\n.*$gdb_prompt " { | |
96 | pass $test | |
97 | set attached 1 | |
98 | } | |
99 | } | |
100 | ||
101 | if {!$attached} { | |
102 | kill_wait_spawned_process $test_spawn_id | |
103 | return | |
104 | } | |
105 | ||
106 | set running_count 0 | |
107 | gdb_test_multiple "info threads" "all threads running" { | |
108 | -re "\\(running\\)" { | |
109 | incr running_count | |
110 | exp_continue | |
111 | } | |
112 | -re "Cannot execute this command while the target is running.*$gdb_prompt $" { | |
113 | # Testing against a remote server that doesn't do | |
114 | # non-stop mode. Explicitly interrupt. This doesn't | |
115 | # test the same code paths in GDB, but it's still | |
116 | # something. | |
117 | gdb_test_multiple "interrupt" "" { | |
118 | -re "$gdb_prompt " { | |
119 | gdb_test_multiple "" $gdb_test_name { | |
120 | -re "received signal SIGINT, Interrupt" { | |
121 | pass $gdb_test_name | |
122 | } | |
123 | } | |
124 | } | |
125 | } | |
126 | } | |
127 | -re "$gdb_prompt $" { | |
128 | gdb_assert {$running_count == ($n_threads + 1)} $gdb_test_name | |
129 | } | |
130 | } | |
131 | } | |
132 | ||
133 | gdb_test "detach" "Detaching from.*" | |
134 | ||
135 | kill_wait_spawned_process $test_spawn_id | |
136 | } | |
137 | ||
138 | if {[build_executable "failed to prepare" $testfile $srcfile {debug pthreads}] == -1} { | |
139 | return -1 | |
140 | } | |
141 | ||
142 | foreach_with_prefix target-non-stop {"off" "on"} { | |
143 | foreach_with_prefix non-stop {"off" "on"} { | |
144 | foreach_with_prefix cmd {"attach" "attach&"} { | |
145 | test ${target-non-stop} ${non-stop} ${cmd} | |
146 | } | |
147 | } | |
148 | } |