diff --git a/gdb/infrun.c b/gdb/infrun.c index 8286026e6c6..72852e63906 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -713,7 +713,7 @@ holding the child stopped. Try \"set detach-on-fork\" or \ (do not restore the parent as the current inferior). */ gdb::optional maybe_restore; - if (!follow_child) + if (!follow_child && !sched_multi) maybe_restore.emplace (); switch_to_thread (*child_inf->threads ().begin ()); @@ -3400,8 +3400,10 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal) struct gdbarch *gdbarch; CORE_ADDR pc; - /* If we're stopped at a fork/vfork, follow the branch set by the - "set follow-fork-mode" command; otherwise, we'll just proceed + /* If we're stopped at a fork/vfork, switch to either the parent or child + thread as defined by the "set follow-fork-mode" command, or, if both + the parent and child are controlled by GDB, and schedule-multiple is + on, follow the child. If none of the above apply then we just proceed resuming the current thread. */ if (!follow_fork ()) { diff --git a/gdb/testsuite/gdb.base/vfork-follow-parent.c b/gdb/testsuite/gdb.base/vfork-follow-parent.c index df45b9c2dbe..15ff84a0bad 100644 --- a/gdb/testsuite/gdb.base/vfork-follow-parent.c +++ b/gdb/testsuite/gdb.base/vfork-follow-parent.c @@ -17,6 +17,10 @@ #include +#include +#include +#include + static volatile int unblock_parent = 0; static void @@ -25,7 +29,7 @@ break_parent (void) } int -main (void) +main (int argc, char **argv) { alarm (30); @@ -40,7 +44,28 @@ main (void) break_parent (); } else - _exit (0); + { +#if defined TEST_EXEC + char prog[PATH_MAX]; + int len; + + strcpy (prog, argv[0]); + len = strlen (prog); + for (; len > 0; --len) + { + if (prog[len - 1] == '/') + break; + } + strcpy (&prog[len], "vforked-prog"); + execlp (prog, prog, (char *) 0); + perror ("exec failed"); + _exit (1); +#elif defined TEST_EXIT + _exit (0); +#else +#error Define TEST_EXEC or TEST_EXIT +#endif + } return 0; } diff --git a/gdb/testsuite/gdb.base/vfork-follow-parent.exp b/gdb/testsuite/gdb.base/vfork-follow-parent.exp index 89c38001dac..70b54e729a5 100644 --- a/gdb/testsuite/gdb.base/vfork-follow-parent.exp +++ b/gdb/testsuite/gdb.base/vfork-follow-parent.exp @@ -19,10 +19,28 @@ # schedule-multiple on" or "set detach-on-fork on". Test these two resolution # methods. -standard_testfile +standard_testfile .c vforked-prog.c -if { [build_executable "failed to prepare" \ - ${testfile} ${srcfile}] } { +set binfile ${testfile}-exit +set binfile2 ${testfile}-exec +set binfile3 vforked-prog + +if { [build_executable "compile $binfile3" $binfile3 $srcfile2] } { + untested "failed to compile third test binary" + return -1 +} + +set remote_exec_prog [gdb_remote_download target $binfile3] + +set opts [list debug additional_flags=-DTEST_EXIT] +if { [build_executable "compile ${binfile}" ${binfile} ${srcfile} ${opts}] } { + untested "failed to compile first test binary" + return +} + +set opts [list debug additional_flags=-DTEST_EXEC] +if { [build_executable "compile ${binfile2}" ${binfile2} ${srcfile} ${opts}] } { + untested "failed to compile second test binary" return } @@ -31,8 +49,12 @@ if { [build_executable "failed to prepare" \ # or "schedule-multiple" (the two alternatives the message suggests to the # user). -proc do_test { resolution_method } { - clean_restart $::binfile +proc do_test { exec_file resolution_method target_non_stop non_stop } { + save_vars { ::GDBFLAGS } { + append ::GDBFLAGS " -ex \"maint set target-non-stop ${target_non_stop}\"" + append ::GDBFLAGS " -ex \"set non-stop ${non_stop}\"" + clean_restart $exec_file + } gdb_test_no_output "set detach-on-fork off" @@ -40,6 +62,10 @@ proc do_test { resolution_method } { return } + # Delete the breakpoint on main so we don't bit the breakpoint in + # the case that the vfork child performs an exec. + delete_breakpoints + gdb_test "break break_parent" gdb_test "continue" \ @@ -75,6 +101,16 @@ proc do_test { resolution_method } { "continue to break_parent" } -foreach_with_prefix resolution_method {detach-on-fork schedule-multiple} { - do_test $resolution_method +foreach_with_prefix exec_file [list $binfile $binfile2] { + foreach_with_prefix target-non-stop {on off} { + # This test was written assuming non-stop mode is off. + foreach_with_prefix non-stop {off} { + if {!${target-non-stop} && ${non-stop}} { + continue + } + foreach_with_prefix resolution_method {detach-on-fork schedule-multiple} { + do_test $exec_file $resolution_method ${target-non-stop} ${non-stop} + } + } + } }