xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/testsuite/gdb.base/fork-running-state.exp (revision a8c74629f602faa0ccf8a463757d7baf858bbf3a)
1# Copyright (C) 2016-2019 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# Regression test for PR threads/19461 (strange "info thread" behavior
17# in non-stop).  GDB used to miss updating the parent/child running
18# states after a fork.
19
20standard_testfile
21
22# The test proper.
23
24proc do_test { detach_on_fork follow_fork non_stop schedule_multiple } {
25    global GDBFLAGS
26    global srcfile testfile
27    global gdb_prompt
28
29    save_vars { GDBFLAGS } {
30	append GDBFLAGS " -ex \"set non-stop $non_stop\""
31
32	if {[prepare_for_testing "failed to prepare" \
33		 $testfile $srcfile {debug}] == -1} {
34	    return -1
35	}
36    }
37
38    if ![runto_main] then {
39	fail "can't run to main"
40	return 0
41    }
42
43    # If debugging with target remote, check whether the all-stop
44    # variant of the RSP is being used.  If so, we can't run the
45    # all-stop tests.
46    if { [target_info exists gdb_protocol]
47	 && ([target_info gdb_protocol] == "remote"
48	     || [target_info gdb_protocol] == "extended-remote")} {
49
50	set test "maint show target-non-stop"
51	gdb_test_multiple "maint show target-non-stop" $test {
52	    -re "(is|currently) on.*$gdb_prompt $" {
53	    }
54	    -re "(is|currently) off.*$gdb_prompt $" {
55		unsupported "can't issue info threads while target is running"
56		return 0
57	    }
58	}
59    }
60
61    # We want to catch "[New inferior ...]" below, to avoid sleeping.
62    if {$detach_on_fork == "off" || $follow_fork == "child"} {
63	gdb_test_no_output "set print inferior-events on"
64    }
65
66    gdb_test_no_output "set detach-on-fork $detach_on_fork"
67
68    gdb_test_no_output "set follow-fork $follow_fork"
69    if {$non_stop == "off"} {
70	gdb_test_no_output "set schedule-multiple $schedule_multiple"
71    }
72
73    # If we're detaching from the parent (or child), then tell it to
74    # exit itself when its child (or parent) exits.  If we stay
75    # attached, we take care of killing it.
76    if {$detach_on_fork == "on"} {
77	gdb_test "print exit_if_relative_exits = 1" " = 1"
78    }
79
80    set test "continue &"
81    gdb_test_multiple $test $test {
82	-re "$gdb_prompt " {
83	    pass $test
84	}
85    }
86
87    if {$detach_on_fork == "off" || $follow_fork == "child"} {
88	set test "fork child appears"
89	gdb_test_multiple "" $test {
90	    -re "\\\[New inferior " {
91		pass $test
92	    }
93	}
94    } else {
95	# All we can do is wait a little bit for the parent to fork.
96	sleep 1
97    }
98
99    set not_nl "\[^\r\n\]*"
100
101    if {$detach_on_fork == "on" && $non_stop == "on" && $follow_fork == "child"} {
102	gdb_test "info threads" \
103	    "  2.1 ${not_nl}\\\(running\\\).*No selected thread.*"
104    } elseif {$detach_on_fork == "on" && $follow_fork == "child"} {
105	gdb_test "info threads" \
106	    "\\\* 2.1 ${not_nl}\\\(running\\\)"
107    } elseif {$detach_on_fork == "on"} {
108	gdb_test "info threads" \
109	    "\\\* 1 ${not_nl}\\\(running\\\)"
110    } elseif {$non_stop == "on"
111	      || ($schedule_multiple == "on" && $follow_fork == "parent")} {
112	# Both parent and child should be marked running, and the
113	# parent should be selected.
114	gdb_test "info threads" \
115	    [multi_line \
116		 "\\\* 1.1 ${not_nl} \\\(running\\\)${not_nl}" \
117		 "  2.1 ${not_nl} \\\(running\\\)"]
118    } elseif {$schedule_multiple == "on" && $follow_fork == "child"} {
119	# Both parent and child should be marked running, and the
120	# child should be selected.
121	gdb_test "info threads" \
122	    [multi_line \
123		 "  1.1 ${not_nl} \\\(running\\\)${not_nl}" \
124		 "\\\* 2.1 ${not_nl} \\\(running\\\)"]
125    } else {
126	set test "only $follow_fork marked running"
127	gdb_test_multiple "info threads" $test {
128	    -re "\\\(running\\\)${not_nl}\\\(running\\\)\r\n$gdb_prompt $" {
129		fail $test
130	    }
131	    -re "\\\* 1.1 ${not_nl}\\\(running\\\)\r\n  2.1 ${not_nl}\r\n$gdb_prompt $" {
132		gdb_assert [string eq $follow_fork "parent"] $test
133	    }
134	    -re "1.1 ${not_nl}\r\n\\\* 2.1 ${not_nl}\\\(running\\\)\r\n$gdb_prompt $" {
135		gdb_assert [string eq $follow_fork "child"] $test
136	    }
137	}
138    }
139
140    # We don't want to see "Inferior exited" in reaction to the kills.
141    gdb_test_no_output "set print inferior-events off"
142
143    # Kill both parent and child.
144    if {$detach_on_fork == "off" || $follow_fork == "parent"} {
145	gdb_test_no_output "kill inferior 1" "kill parent"
146    }
147    if {$detach_on_fork == "off" || $follow_fork == "child"} {
148	gdb_test_no_output "kill inferior 2" "kill child"
149    }
150}
151
152# Exercise all permutations of:
153#
154#  set detach-on-fork off|on
155#  set follow-fork parent|child
156#  set non-stop on|off
157#  set schedule-multiple on|off
158
159foreach_with_prefix detach-on-fork {"off" "on"} {
160    foreach_with_prefix follow-fork {"parent" "child"} {
161	with_test_prefix "non-stop" {
162	    do_test ${detach-on-fork} ${follow-fork} "on" "-"
163	}
164	with_test_prefix "all-stop" {
165	    foreach_with_prefix schedule-multiple {"on" "off"} {
166		do_test ${detach-on-fork} ${follow-fork} "off" ${schedule-multiple}
167	    }
168	}
169    }
170}
171