]>
Commit | Line | Data |
---|---|---|
1d506c26 | 1 | # Copyright 2022-2024 Free Software Foundation, Inc. |
bd9482bc 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 catching a vfork/fork in one thread, and then doing a "next" in | |
17 | # another thread, in different combinations of "set follow-fork | |
18 | # parent/child", and other execution modes. | |
19 | ||
20 | standard_testfile | |
21 | ||
22 | # Line where to stop the main thread. | |
23 | set break_here_line [gdb_get_line_number "break here"] | |
24 | ||
25 | # Build executables, one for each fork flavor. | |
26 | foreach_with_prefix fork_func {fork vfork} { | |
27 | set opts [list debug pthreads additional_flags=-DFORK_FUNC=${fork_func}] | |
28 | if { [build_executable "failed to prepare" \ | |
29 | ${testfile}-${fork_func} ${srcfile} $opts] } { | |
30 | return | |
31 | } | |
32 | } | |
33 | ||
34 | # Run the test with the given parameters: | |
35 | # | |
36 | # - FORK_FUNC: fork flavor, "fork" or "vfork". | |
37 | # - FOLLOW: "set follow-fork" value, either "parent" or "child". | |
38 | # - TARGET-NON-STOP: "maintenance set target-non-stop" value, "auto", "on" or | |
39 | # "off". | |
40 | # - NON-STOP: "set non-stop" value, "on" or "off". | |
41 | # - DISPLACED-STEPPING: "set displaced-stepping" value, "auto", "on" or "off". | |
42 | ||
43 | proc do_test { fork_func follow target-non-stop non-stop displaced-stepping } { | |
44 | save_vars { ::GDBFLAGS } { | |
45 | append ::GDBFLAGS " -ex \"maintenance set target-non-stop ${target-non-stop}\"" | |
46 | append ::GDBFLAGS " -ex \"set non-stop ${non-stop}\"" | |
47 | clean_restart ${::binfile}-${fork_func} | |
48 | } | |
49 | ||
50 | gdb_test_no_output "set displaced-stepping ${displaced-stepping}" | |
51 | ||
52 | if { ![runto_main] } { | |
53 | return | |
54 | } | |
55 | ||
56 | delete_breakpoints | |
57 | ||
58 | gdb_test "catch $fork_func" "Catchpoint .*" | |
59 | ||
60 | # Verify that the catchpoint is mentioned in an "info breakpoints", | |
61 | # and further that the catchpoint mentions no process id. | |
62 | gdb_test "info breakpoints" \ | |
e2f62013 | 63 | ".*catchpoint.*keep y.*fork" \ |
bd9482bc PA |
64 | "info breakpoints before fork" |
65 | ||
66 | gdb_test "continue" \ | |
67 | "Catchpoint \[0-9\]* \\(.?forked process \[0-9\]*\\),.*" \ | |
68 | "explicit child follow, catch fork" | |
69 | ||
70 | # Verify that the catchpoint is mentioned in an "info breakpoints", | |
71 | # and further that the catchpoint managed to capture a process id. | |
72 | gdb_test "info breakpoints" \ | |
73 | ".*catchpoint.*keep y.*fork, process.*" \ | |
74 | "info breakpoints after fork" | |
75 | ||
76 | gdb_test "thread 1" "Switching to .*" | |
77 | ||
78 | gdb_test_no_output "set scheduler-locking on" | |
79 | ||
80 | # Advance the next-ing thread to the point where we'll execute the | |
81 | # next. | |
82 | gdb_test "break $::srcfile:$::break_here_line" "Breakpoint $::decimal at $::hex.*" | |
83 | gdb_test "continue" "hit Breakpoint $::decimal, main.*" | |
84 | ||
85 | # Disable schedlock and step. The pending fork should no longer | |
86 | # be pending afterwards. | |
87 | ||
88 | gdb_test "set scheduler-locking off" | |
89 | ||
90 | # Make sure GDB doesn't try to step over the breakpoint at PC | |
91 | # first, we want to make sure that GDB doesn't lose focus of the | |
92 | # step/next in this thread. A breakpoint would make GDB switch | |
93 | # focus anyhow, thus hide a potential bug. | |
94 | delete_breakpoints | |
95 | ||
96 | gdb_test_no_output "set follow-fork $follow" | |
97 | ||
98 | set any "\[^\r\n\]*" | |
99 | ||
100 | if {$follow == "child"} { | |
101 | ||
102 | # For fork, GDB detaches from the parent at follow-fork time. | |
103 | # For vfork, GDB detaches from the parent at child exit/exec | |
104 | # time. | |
105 | if {$fork_func == "fork"} { | |
106 | set detach_parent \ | |
107 | [multi_line \ | |
108 | "\\\[Detaching after $fork_func from parent process $any\\\]" \ | |
109 | "\\\[Inferior 1 $any detached\\\]"] | |
110 | } else { | |
111 | set detach_parent "" | |
112 | } | |
113 | ||
114 | gdb_test "next" \ | |
115 | [multi_line \ | |
116 | "\\\[Attaching after $any $fork_func to child $any\\\]" \ | |
117 | "\\\[New inferior 2 $any\\\]" \ | |
118 | "$detach_parent.*warning: Not resuming: switched threads before following fork child\\." \ | |
119 | "\\\[Switching to $any\\\]" \ | |
120 | ".*"] \ | |
121 | "next aborts resumption" | |
122 | ||
123 | # The child should be stopped inside the fork implementation | |
124 | # in the runtime. Exactly at which instruction/function is | |
125 | # system dependent, but we can check that our | |
126 | # "gdb_forker_thread" function appears in the backtrace. | |
127 | gdb_test "bt" " in gdb_forker_thread ${any} at ${any}${::srcfile}:.*" | |
128 | ||
129 | # The child is now thread 1. | |
130 | gdb_test "print \$_thread" " = 1" | |
131 | ||
132 | if {$fork_func == "fork"} { | |
133 | gdb_test "continue" \ | |
134 | [multi_line \ | |
135 | "Continuing." \ | |
136 | "\\\[Inferior 2 \\\(process $any\\\) exited normally\\\]"] \ | |
137 | "continue to exit" | |
138 | } else { | |
139 | gdb_test "continue" \ | |
140 | [multi_line \ | |
141 | "Continuing." \ | |
142 | "\\\[Detaching vfork parent process $any after child exit\\\]" \ | |
143 | "\\\[Inferior 1 \\\(process $any\\\) detached\\\]" \ | |
144 | "\\\[Inferior 2 \\\(process $any\\\) exited normally\\\]"] \ | |
145 | "continue to exit" | |
146 | } | |
147 | } else { | |
148 | gdb_test "next" \ | |
149 | "\\\[Detaching after $fork_func from child process ${any}\\\].* other line .*" \ | |
150 | "next to other line" | |
151 | ||
152 | gdb_test "print \$_thread" " = 1" | |
153 | ||
154 | gdb_test "continue" \ | |
155 | [multi_line \ | |
156 | "Continuing." \ | |
157 | "\\\[Inferior 1 \\\(process $any\\\) exited normally\\\]"] \ | |
158 | "continue to exit" | |
159 | } | |
160 | } | |
161 | ||
162 | foreach_with_prefix fork_func {fork vfork} { | |
163 | foreach_with_prefix follow {child} { | |
164 | foreach_with_prefix target-non-stop {auto on off} { | |
165 | foreach_with_prefix non-stop {off} { | |
166 | foreach_with_prefix displaced-stepping {auto on off} { | |
167 | do_test ${fork_func} ${follow} ${target-non-stop} ${non-stop} ${displaced-stepping} | |
168 | } | |
169 | } | |
170 | } | |
171 | } | |
172 | } |