diff --git a/gdb/testsuite/gdb.base/foll-vfork.exp b/gdb/testsuite/gdb.base/foll-vfork.exp
index bdceff0f5de..be0715b05c0 100644
--- a/gdb/testsuite/gdb.base/foll-vfork.exp
+++ b/gdb/testsuite/gdb.base/foll-vfork.exp
@@ -25,56 +25,52 @@ if {![istarget "*-linux*"]} {
     continue
 }
 
-standard_testfile
+standard_testfile .c -exit.c vforked-prog.c
 
-set compile_options debug
+set binfile $testfile
+set binfile2 ${testfile}-exit
+set binfile3 vforked-prog
 
-if {[build_executable $testfile.exp $testfile $srcfile $compile_options] == -1} {
+if {[build_executable "compile $binfile" $binfile $srcfile] == -1} {
     untested "failed to compile main testcase"
     return -1
 }
 
-set testfile2 "vforked-prog"
-set srcfile2 ${testfile2}.c
+if {[build_executable "compile $binfile2" $binfile2 $srcfile2] == -1} {
+    untested "failed to compile main testcase"
+    return -1
+}
 
-if {[build_executable $testfile.exp $testfile2 $srcfile2 $compile_options] == -1} {
-    untested "failed to compile secondary testcase"
+if {[build_executable "compile $binfile3" $binfile3 $srcfile3] == -1} {
+    untested "failed to compile main testcase"
     return -1
 }
 
+# If required, download the program that we exec after vfork to the
+# remote target.
 if { [is_remote target] } {
-    gdb_remote_download target [standard_output_file $testfile2]
+    gdb_remote_download target [standard_output_file $binfile3]
 }
 
-# A few of these tests require a little more time than the standard
-# timeout allows.
-set oldtimeout $timeout
-set timeout [expr "$timeout + 10"]
-
 # Start with a fresh GDB, with verbosity enabled, and run to main.  On
 # error, behave as "return", so we don't try to continue testing with
 # a borked session.
-proc setup_gdb {} {
-    global testfile srcfile
-
-    clean_restart $testfile
+proc setup_gdb { binfile srcfile } {
+    clean_restart $binfile
 
     if ![runto_main] {
 	return -code return
     }
 
-    set tbreak_line [gdb_get_line_number " VFORK " $srcfile]
-    gdb_test "tbreak ${tbreak_line}"
-    gdb_continue_to_breakpoint ".*"
+    gdb_breakpoint [gdb_get_line_number " VFORK " $srcfile] temporary
+    gdb_continue_to_breakpoint "at VFORK"
 }
 
 proc check_vfork_catchpoints {} {
-  global gdb_prompt
-
   # Because setup_gdb uses 'return -code return' which would return to
   # our caller we need to wrap this call, spot when setup_gdb failed
   # (with return code 2), and then issue our own 'return -code return'.
-  set code [catch {setup_gdb} string]
+  set code [catch {setup_gdb $::testfile $::srcfile} string]
   if { $code == 2 } {
     unsupported "vfork catchpoints"
     return -code return
@@ -84,10 +80,10 @@ proc check_vfork_catchpoints {} {
   gdb_test "catch vfork" "Catchpoint \[0-9\]* \\(vfork\\)" "insert first vfork catchpoint"
   set has_vfork_catchpoints 0
   gdb_test_multiple "continue" "continue to first vfork catchpoint" {
-    -re ".*Your system does not support this type\r\nof catchpoint.*$gdb_prompt $" {
+    -re -wrap ".*Your system does not support this type\r\nof catchpoint.*" {
       unsupported "continue to first vfork catchpoint"
     }
-    -re ".*Catchpoint.*$gdb_prompt $" {
+    -re -wrap ".*Catchpoint.*" {
       set has_vfork_catchpoints 1
       pass "continue to first vfork catchpoint"
     }
@@ -99,319 +95,278 @@ proc check_vfork_catchpoints {} {
   }
 }
 
-proc vfork_parent_follow_through_step {} {
-  with_test_prefix "vfork parent follow, through step" {
-   global gdb_prompt
+proc_with_prefix vfork_parent_follow_through_step { binfile srcfile } {
+    setup_gdb $binfile $srcfile
 
-   setup_gdb
+    gdb_test_no_output "set follow-fork parent"
 
-   gdb_test_no_output "set follow-fork parent"
+    gdb_test_multiple "next" "" {
+	-re -wrap "\\\[Detaching after vfork from.*if \\(pid == 0\\).*" {
+	    pass $gdb_test_name
+	}
+    }
 
-   set test "step"
-   gdb_test_multiple "next" $test {
-       -re "\\\[Detaching after vfork from.*if \\(pid == 0\\).*$gdb_prompt " {
-	   pass $test
-       }
-   }
-   # The child 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_parent_follow_to_bp {} {
-  with_test_prefix "vfork parent follow, to bp" {
-   global gdb_prompt
-   global srcfile
-
-   setup_gdb
-
-   gdb_test_no_output "set follow-fork parent"
-
-   set bp_location [gdb_get_line_number "I'm the proud parent of child"]
-   gdb_test "break ${srcfile}:${bp_location}" ".*" "break, vfork to bp"
-
-   set test "continue to bp"
-   gdb_test_multiple "continue" $test {
-       -re ".*\\\[Detaching after vfork from child process.*Breakpoint.*${bp_location}.*$gdb_prompt " {
-	   pass $test
-       }
-   }
-   # The child 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
-}}
-
-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 " {
-	  # PR 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
-}}
+    # The child 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
-   global srcfile2
+proc_with_prefix vfork_parent_follow_to_bp { binfile srcfile } {
+    setup_gdb $binfile $srcfile
 
-   setup_gdb
+    gdb_test_no_output "set follow-fork parent"
 
-   gdb_test_no_output "set follow-fork child"
+    set bp_location \
+	[gdb_get_line_number "I'm the proud parent of child" $srcfile]
+    gdb_test "break ${srcfile}:${bp_location}" ".*" "break, vfork to bp"
 
-   set linenum [gdb_get_line_number "Hello from vforked-prog" ${srcfile2}]
+    gdb_test_multiple "continue" "continue to bp" {
+	-re -wrap ".*\\\[Detaching after vfork from child process.*Breakpoint.*${bp_location}.*" {
+	    pass $gdb_test_name
+	}
+    }
 
-   set test "continue to bp"
-   gdb_test_multiple "continue" $test {
-      -re "\\\[Attaching after.* vfork to.*\\\[Detaching vfork parent.*xecuting new program.*Breakpoint.*vforked-prog.c:${linenum}.*$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_through_step {} {
-  with_test_prefix "vfork and exec child follow, through step" {
-   global gdb_prompt
-   global srcfile2
-
-   setup_gdb
-
-   gdb_test_no_output "set follow-fork child"
-
-   set test "step over vfork"
-
-   # The ideal support is to be able to debug the child even
-   # before it execs.  Thus, "next" lands on the next line after
-   # the vfork.
-   gdb_test_multiple "next" $test {
-       -re "\\\[Attaching after .* vfork to child.*if \\(pid == 0\\).*$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 expected debugger output from a subsequent testpoint.
-   #
-   exec sleep 1
-}}
+    # The child 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
+}
+
+proc_with_prefix vfork_child_follow_to_exit { binfile srcfile } {
+    setup_gdb $binfile $srcfile
+
+    gdb_test_no_output "set follow-fork child"
+
+    gdb_test_multiple "continue" "continue to child exit" {
+	-re -wrap "Couldn't get registers.*" {
+	    # PR gdb/14766
+	    fail $gdb_test_name
+	}
+	-re -wrap "\\\[Attaching after.* vfork to.*\\\[Detaching vfork parent .* after child exit.*" {
+	    pass $gdb_test_name
+	}
+    }
+
+    # 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_with_prefix vfork_and_exec_child_follow_to_main_bp { binfile srcfile } {
+    setup_gdb $binfile $srcfile
+
+    gdb_test_no_output "set follow-fork child"
+
+    set linenum [gdb_get_line_number "Hello from vforked-prog" ${::srcfile3}]
+
+    gdb_test_multiple "continue" "continue to bp" {
+	-re -wrap "\\\[Attaching after.* vfork to.*\\\[Detaching vfork parent.*xecuting new program.*Breakpoint.*vforked-prog.c:${linenum}.*" {
+	    pass $gdb_test_name
+	}
+    }
+
+    # 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_with_prefix vfork_and_exec_child_follow_through_step { binfile srcfile } {
+    setup_gdb $binfile $srcfile
+
+    gdb_test_no_output "set follow-fork child"
+
+    # The ideal support is to be able to debug the child even
+    # before it execs.  Thus, "next" lands on the next line after
+    # the vfork.
+    gdb_test_multiple "next" "next over vfork" {
+	-re -wrap "\\\[Attaching after .* vfork to child.*if \\(pid == 0\\).*" {
+	    pass $gdb_test_name
+	}
+    }
+
+    # 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
+}
 
 proc continue_to_vfork {} {
-   global gdb_prompt
-
-   # A vfork catchpoint may stop in either "vfork" or "_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
-      }
-   }
+    # A vfork catchpoint may stop in either "vfork" or "_vfork".
+    gdb_test_multiple "continue" "continue to vfork" {
+	-re -wrap "vfork \\(\\) at .*" {
+	    pass $gdb_test_name
+	}
+	-re -wrap "0x\[0-9a-fA-F\]*.*(vfork|__kernel_v?syscall).*" {
+	    pass $gdb_test_name
+	}
+    }
 }
 
-proc tcatch_vfork_then_parent_follow {} {
-  with_test_prefix "vfork parent follow, finish after tcatch vfork" {
-   global gdb_prompt
-   global srcfile
-
-   setup_gdb
-
-   gdb_test_no_output "set follow-fork parent"
-
-   gdb_test "tcatch vfork" "Catchpoint .*(vfork).*"
-
-   continue_to_vfork
-
-   set linenum [gdb_get_line_number "pid = vfork ();"]
-   set test "finish"
-   gdb_test_multiple "finish" $test {
-      -re "Run till exit from.*vfork.*0x\[0-9a-fA-F\]* in main .* at .*${srcfile}:${linenum}.*$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 child 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
-}}
-
-proc tcatch_vfork_then_child_follow_exec {} {
-  with_test_prefix "vfork child follow, finish after tcatch vfork" {
-   global gdb_prompt
-   global srcfile
-   global srcfile2
-
-   setup_gdb
-
-   gdb_test_no_output "set follow-fork child"
-
-   gdb_test "tcatch vfork" "Catchpoint .*(vfork).*"
-
-   continue_to_vfork
-
-   set linenum1 [gdb_get_line_number "pid = vfork ();"]
-   set linenum2 [gdb_get_line_number "Hello from vforked-prog" ${srcfile2}]
-
-   set test "finish"
-   gdb_test_multiple "finish" $test {
-      -re "Run till exit from.*vfork.*${srcfile}:${linenum1}.*$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
-      }
-      -re "Run till exit from.*vfork.*${srcfile2}:${linenum2}.*$gdb_prompt " {
-	  pass "$test (followed exec)"
-      }
-   }
-   # 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
-}}
-
-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).*"
-
-   continue_to_vfork
-
-   set test "finish"
-   gdb_test_multiple "finish" $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
-}}
+proc_with_prefix tcatch_vfork_then_parent_follow { binfile srcfile } {
+    setup_gdb $binfile $srcfile
 
-proc vfork_relations_in_info_inferiors { variant } {
-  with_test_prefix "vfork relations in info inferiors" {
-   global gdb_prompt
+    gdb_test_no_output "set follow-fork parent"
 
-   setup_gdb
+    gdb_test "tcatch vfork" "Catchpoint .*(vfork).*"
 
-   gdb_test_no_output "set follow-fork child"
+    continue_to_vfork
 
-   set test "step over vfork"
-   gdb_test_multiple "next" $test {
-       -re "\\\[Attaching after .* vfork to child.*if \\(pid == 0\\).*$gdb_prompt " {
-	   pass "$test"
-       }
-   }
+    set linenum [gdb_get_line_number "pid = vfork ();" $srcfile]
+    gdb_test_multiple "finish" "" {
+	-re -wrap "Run till exit from.*vfork.*0x\[0-9a-fA-F\]* in main .* at .*${srcfile}:${linenum}.*" {
+	    pass $gdb_test_name
+	}
+	-re -wrap "Run till exit from.*__kernel_v?syscall.*0x\[0-9a-fA-F\]* in vfork .*" {
+	    send_gdb "finish\n"
+	    exp_continue
+	}
+    }
 
-   gdb_test "info inferiors" \
-       ".*is vfork parent of inferior 2.*is vfork child of inferior 1" \
-       "info inferiors shows vfork parent/child relation"
+    # The child 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
+}
 
-   if { $variant == "exec" } {
-       global srcfile2
+proc_with_prefix tcatch_vfork_then_child_follow_exec { binfile srcfile } {
+    setup_gdb $binfile $srcfile
 
-       set linenum [gdb_get_line_number "Hello from vforked-prog" ${srcfile2}]
-       set test "continue to bp"
-       gdb_test_multiple "continue" $test {
-	   -re ".*xecuting new program.*Breakpoint.*vforked-prog.c:${linenum}.*$gdb_prompt " {
-	       pass $test
-	   }
-       }
-   } else {
-       set test "continue to child exit"
-       gdb_test_multiple "continue" $test {
-	   -re "exited normally.*$gdb_prompt " {
-	       pass $test
+    gdb_test_no_output "set follow-fork child"
+
+    gdb_test "tcatch vfork" "Catchpoint .*(vfork).*"
+
+    continue_to_vfork
+
+    set linenum1 [gdb_get_line_number "pid = vfork ();" $srcfile]
+    set linenum2 [gdb_get_line_number "Hello from vforked-prog" ${::srcfile3}]
+
+    gdb_test_multiple "finish" "" {
+	-re -wrap "Run till exit from.*vfork.*${srcfile}:${linenum1}.*" {
+	  pass $gdb_test_name
+	}
+	-re -wrap "Run till exit from.*__kernel_v?syscall.*0x\[0-9a-fA-F\]* in vfork .*" {
+	    send_gdb "finish\n"
+	    exp_continue
+	}
+	-re -wrap "Run till exit from.*vfork.*${::srcfile3}:${linenum2}.*" {
+	    pass "$gdb_test_name (followed exec)"
+	}
+    }
+
+    # 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
+}
+
+proc tcatch_vfork_then_child_follow_exit { binfile srcfile } {
+   setup_gdb $binfile $srcfile
+
+    gdb_test_no_output "set follow-fork child"
+
+    gdb_test "tcatch vfork" "Catchpoint .*(vfork).*"
+
+    continue_to_vfork
+
+    gdb_test_multiple "finish" "" {
+	-re -wrap "Run till exit from.*vfork.*exited normally.*" {
+	    setup_kfail "gdb/14762" *-*-*
+	    fail $gdb_test_name
+	}
+	-re -wrap "Run till exit from.*vfork.*pid = vfork \\(\\).*" {
+	  pass $gdb_test_name
+	}
+	-re -wrap "Run till exit from.*__kernel_v?syscall.*0x\[0-9a-fA-F\]* in vfork .*" {
+	    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
+}
+
+proc_with_prefix vfork_relations_in_info_inferiors { variant binfile srcfile non_stop } {
+    setup_gdb $binfile $srcfile
+
+    gdb_test_no_output "set follow-fork child"
+
+    gdb_test_multiple "next" "next over vfork" {
+	-re -wrap "\\\[Attaching after .* vfork to child.*if \\(pid == 0\\).*" {
+	    pass $gdb_test_name
+	}
+    }
+
+    if { $non_stop } {
+	gdb_test "inferior 2" ".*"
+    }
+
+    gdb_test "info inferiors" \
+	".*is vfork parent of inferior 2.*is vfork child of inferior 1" \
+	"info inferiors shows vfork parent/child relation"
+
+    if { $variant == "exec" } {
+	set linenum [gdb_get_line_number "Hello from vforked-prog" ${::srcfile3}]
+	gdb_test_multiple "continue" "continue to bp" {
+	    -re -wrap ".*xecuting new program.*Breakpoint.*vforked-prog.c:${linenum}.*" {
+		pass $gdb_test_name
+	    }
+	}
+    } else {
+	gdb_test_multiple "continue" "continue to child exit" {
+	   -re -wrap "exited normally.*" {
+	       pass $gdb_test_name
 	   }
-       }
-   }
-
-   set test "vfork relation no longer appears in info inferiors"
-   gdb_test_multiple "info inferiors" $test {
-       -re -wrap "is vfork child of inferior 1.*" {
-	   fail $test
-       }
-       -re -wrap "is vfork parent of inferior 2.*" {
-	   fail $test
-       }
-       -re -wrap "" {
-	   pass $test
-       }
-   }
-}}
-
-proc do_vfork_and_follow_parent_tests {} {
-   global gdb_prompt
+	}
+    }
 
+    gdb_test_multiple "info inferiors" "vfork relation no longer appears in info inferiors" {
+	-re -wrap "is vfork child of inferior 1.*" {
+	   fail $gdb_test_name
+	}
+	-re -wrap "is vfork parent of inferior 2.*" {
+	    fail $gdb_test_name
+	}
+	-re -wrap "" {
+	    pass $gdb_test_name
+	}
+    }
+}
+
+proc do_vfork_and_follow_parent_tests { binfile srcfile } {
    # Try following the parent process by stepping through a call to
    # vfork.  Do this without catchpoints.
-   vfork_parent_follow_through_step
+   vfork_parent_follow_through_step $binfile $srcfile
 
    # Try following the parent process by setting a breakpoint on the
    # other side of a vfork, and running to that point.  Do this
    # without catchpoints.
-   vfork_parent_follow_to_bp
+   vfork_parent_follow_to_bp $binfile $srcfile
 
    # Try catching a vfork, and stepping out to the parent.
    #
-   tcatch_vfork_then_parent_follow
+   tcatch_vfork_then_parent_follow $binfile $srcfile
 }
 
-proc do_vfork_and_follow_child_tests_exec {} {
+proc do_vfork_and_follow_child_tests_exec { binfile srcfile non_stop } {
    # 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_to_main_bp
+   vfork_and_exec_child_follow_to_main_bp $binfile $srcfile
 
    # Try following the child process by stepping through a call to
    # vfork.  The child also executes an exec.  Since the child cannot
@@ -420,11 +375,11 @@ proc do_vfork_and_follow_child_tests_exec {} {
    # recomputed in the exec'd child, the step through a vfork should
    # land us in the "main" for the exec'd child, too.
    #
-   vfork_and_exec_child_follow_through_step
+   vfork_and_exec_child_follow_through_step $binfile $srcfile
 
    # Try catching a vfork, and stepping out to the child.
    #
-   tcatch_vfork_then_child_follow_exec
+   tcatch_vfork_then_child_follow_exec $binfile $srcfile
 
    # Test the ability to follow both child and parent of a vfork.  Do
    # this without catchpoints.
@@ -442,25 +397,25 @@ proc do_vfork_and_follow_child_tests_exec {} {
    # and confirm the relation is no longer displayed in "info
    # inferiors".
    #
-   vfork_relations_in_info_inferiors "exec"
+   vfork_relations_in_info_inferiors "exec" $binfile $srcfile $non_stop
 }
 
-proc do_vfork_and_follow_child_tests_exit {} {
+proc do_vfork_and_follow_child_tests_exit { binfile srcfile non_stop } {
    # Try following the child process by just continuing through the
    # vfork, and letting the child exit.
    #
-   vfork_child_follow_to_exit
+   vfork_child_follow_to_exit $binfile $srcfile
 
    # Try catching a vfork, and stepping out to the child.
    #
-   tcatch_vfork_then_child_follow_exit
+   tcatch_vfork_then_child_follow_exit $binfile $srcfile
 
    # Step over a vfork in the child, do "info inferiors" and check the
    # parent/child relation is displayed.  Run the child to completion,
    # and confirm the relation is no longer displayed in "info
    # inferiors".
    #
-   vfork_relations_in_info_inferiors "exit"
+   vfork_relations_in_info_inferiors "exit" $binfile $srcfile $non_stop
 }
 
 with_test_prefix "check vfork support" {
@@ -470,41 +425,58 @@ with_test_prefix "check vfork support" {
 }
 
 # Follow parent and follow child vfork tests with a child that execs.
-with_test_prefix "exec" {
+proc_with_prefix exec_tests { binfile srcfile non_stop } {
     # 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
+    do_vfork_and_follow_parent_tests $binfile $srcfile
 
     # 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
+    do_vfork_and_follow_child_tests_exec $binfile $srcfile $non_stop
 }
 
 # Follow parent and follow child vfork tests with a child that exits.
-with_test_prefix "exit" {
+proc_with_prefix exit_tests { binfile srcfile non_stop } {
     # 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
+    do_vfork_and_follow_parent_tests $binfile $srcfile
 
     # 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
+    do_vfork_and_follow_child_tests_exit $binfile $srcfile $non_stop
+}
+
+# Using the remote protocol with schedule-multiple turned triggers bug
+# gdb/30574, so avoid this for now.
+if {[target_info exists gdb_protocol]
+    && ([target_info gdb_protocol] == "remote"
+	|| [target_info gdb_protocol] == "extended-remote")} {
+    set sm_modes { off }
+} else {
+    set sm_modes { off on }
 }
 
-set timeout $oldtimeout
+# A few of these tests require a little more time than the standard timeout
+# allows.
+with_timeout_factor 2 {
+    foreach_with_prefix target-non-stop {auto on off} {
+	foreach_with_prefix non-stop {off on} {
+	    foreach_with_prefix schedule-multiple $sm_modes {
+		save_vars { ::GDBFLAGS } {
+		    # These flags will be picked up by the call to
+		    # clean_restart inside setup_gdb.
+		    append ::GDBFLAGS " -ex \"maintenance set target-non-stop ${target-non-stop}\""
+		    append ::GDBFLAGS " -ex \"set non-stop ${non-stop}\""
+		    append ::GDBFLAGS " -ex \"set schedule-multiple ${schedule-multiple}\""
+
+		    exec_tests $binfile $srcfile ${non-stop}
+		    exit_tests $binfile2 $srcfile2 ${non-stop}
+		}
+	    }
+	}
+    }
+}
