# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+# Various tests of gdb's ability to follow the parent or child of a
+# Unix vfork system call. A vfork parent is blocked until the child
+# either execs or exits --- since those events take somewhat different
+# code paths in GDB, both variants are exercised.
+
if { [is_remote target] || ![isnative] } then {
continue
}
exec sleep 1
}}
+proc vfork_child_follow_to_exit {} {
+ with_test_prefix "vfork child follow, to exit" {
+ global gdb_prompt
+
+ setup_gdb
+
+ gdb_test_no_output "set follow-fork child"
+
+ set test "continue to child exit"
+ gdb_test_multiple "continue" $test {
+ -re "Couldn't get registers.*$gdb_prompt " {
+ setup_kfail "gdb/14766" *-*-*
+ fail "$test"
+ }
+ -re "Attaching after.* vfork to.*Detaching vfork parent .* after child exit.*$gdb_prompt " {
+ pass $test
+ }
+ }
+ # The parent has been detached; allow time for any output it might
+ # generate to arrive, so that output doesn't get confused with
+ # any gdb_expected debugger output from a subsequent testpoint.
+ #
+ exec sleep 1
+}}
+
proc vfork_and_exec_child_follow_to_main_bp {} {
with_test_prefix "vfork and exec child follow, to main bp" {
global gdb_prompt
exec sleep 1
}}
-proc tcatch_vfork_then_child_follow {} {
+proc tcatch_vfork_then_child_follow_exec {} {
with_test_prefix "vfork child follow, finish after tcatch vfork" {
global gdb_prompt
global srcfile
exec sleep 1
}}
-proc do_vfork_and_exec_tests {} {
+proc tcatch_vfork_then_child_follow_exit {} {
+ with_test_prefix "vfork child follow, finish after tcatch vfork" {
global gdb_prompt
+ global srcfile
+
+ setup_gdb
+
+ gdb_test_no_output "set follow-fork child"
+
+ gdb_test "tcatch vfork" "Catchpoint .*(vfork).*"
+
+ # HP-UX 10.20 seems to stop you in "vfork", while more recent HP-UXs
+ # stop you in "_vfork".
+ set test "continue to vfork"
+ gdb_test_multiple "continue" $test {
+ -re "vfork \\(\\) at .*$gdb_prompt $" {
+ pass $test
+ }
+ -re "0x\[0-9a-fA-F\]*.*(vfork|__kernel_v?syscall).*$gdb_prompt " {
+ pass $test
+ }
+ }
+
+ set test "finish"
+ gdb_test_multiple "finish" $test {
+ -re "Couldn't get registers.*$gdb_prompt " {
+ setup_kfail "gdb/14766" *-*-*
+ fail "$test "
+ }
+ -re "Run till exit from.*vfork.*exited normally.*$gdb_prompt " {
+ setup_kfail "gdb/14762" *-*-*
+ fail $test
+ }
+ -re "Run till exit from.*vfork.*pid = vfork \\(\\).*$gdb_prompt " {
+ pass $test
+ }
+ -re "Run till exit from.*__kernel_v?syscall.*0x\[0-9a-fA-F\]* in vfork .*$gdb_prompt " {
+ send_gdb "finish\n"
+ exp_continue
+ }
+ }
+ # The parent has been detached; allow time for any output it might
+ # generate to arrive, so that output doesn't get confused with
+ # any expected debugger output from a subsequent testpoint.
+ #
+ exec sleep 1
+}}
- # Check that vfork catchpoints are supported, as an indicator for whether
- # vfork-following is supported.
- check_vfork_catchpoints
+proc do_vfork_and_follow_parent_tests {} {
+ global gdb_prompt
# Try following the parent process by stepping through a call to
# vfork. Do this without catchpoints.
# without catchpoints.
vfork_parent_follow_to_bp
+ # Try catching a vfork, and stepping out to the parent.
+ #
+ tcatch_vfork_then_parent_follow
+}
+
+proc do_vfork_and_follow_child_tests_exec {} {
# Try following the child process by just continuing through the
# vfork, and letting the parent's breakpoint on "main" be auto-
# magically reset in the child.
#
vfork_and_exec_child_follow_through_step
- # Try catching a vfork, and stepping out to the parent.
- #
- tcatch_vfork_then_parent_follow
-
# Try catching a vfork, and stepping out to the child.
#
- tcatch_vfork_then_child_follow
+ tcatch_vfork_then_child_follow_exec
# Test the ability to follow both child and parent of a vfork. Do
# this without catchpoints.
#
}
-# This is a test of gdb's ability to follow the parent or child
-# of a Unix vfork() system call. (The child will subsequently
-# call a variant of a Unix exec() system call.)
-#
-do_vfork_and_exec_tests
+proc do_vfork_and_follow_child_tests_exit {} {
+ # Try following the child process by just continuing through the
+ # vfork, and letting the child exit.
+ #
+ vfork_child_follow_to_exit
+
+ # Try catching a vfork, and stepping out to the child.
+ #
+ tcatch_vfork_then_child_follow_exit
+}
+
+with_test_prefix "check vfork support" {
+ # Check that vfork catchpoints are supported, as an indicator for
+ # whether vfork-following is supported.
+ check_vfork_catchpoints
+}
+
+# Follow parent and follow child vfork tests with a child that execs.
+with_test_prefix "exec" {
+ # These are tests of gdb's ability to follow the parent of a Unix
+ # vfork system call. The child will subsequently call a variant
+ # of the Unix exec system call.
+ do_vfork_and_follow_parent_tests
+
+ # These are tests of gdb's ability to follow the child of a Unix
+ # vfork system call. The child will subsequently call a variant
+ # of a Unix exec system call.
+ #
+ do_vfork_and_follow_child_tests_exec
+}
+
+# Switch to test the case of the child exiting. We can't use
+# standard_testfile here because we don't want to overwrite the binary
+# of the previous tests.
+set testfile "foll-vfork-exit"
+set srcfile ${testfile}.c
+set binfile [standard_output_file ${testfile}]
+
+if {[build_executable $testfile.exp $testfile $srcfile] == -1} {
+ untested "failed to build $testfile"
+ return
+}
+
+# Follow parent and follow child vfork tests with a child that exits.
+with_test_prefix "exit" {
+ # These are tests of gdb's ability to follow the parent of a Unix
+ # vfork system call. The child will subsequently exit.
+ do_vfork_and_follow_parent_tests
+
+ # These are tests of gdb's ability to follow the child of a Unix
+ # vfork system call. The child will subsequently exit.
+ #
+ do_vfork_and_follow_child_tests_exit
+}
set timeout $oldtimeout
return 0