diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 23c8895..11fe5a7 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -154,7 +154,8 @@ struct breakpoint *set_raw_breakpoint (struct
gdbarch *gdbarch,
 static struct breakpoint *
   momentary_breakpoint_from_master (struct breakpoint *orig,
 				    enum bptype type,
-				    const struct breakpoint_ops *ops);
+				    const struct breakpoint_ops *ops,
+				    int loc_enabled);

 static void breakpoint_adjustment_warning (CORE_ADDR, CORE_ADDR, int, int);

@@ -7390,7 +7391,7 @@ set_longjmp_breakpoint (struct thread_info *tp,
struct frame_id frame)
 	/* longjmp_breakpoint_ops ensures INITIATING_FRAME is cleared again
 	   after their removal.  */
 	clone = momentary_breakpoint_from_master (b, type,
-						  &longjmp_breakpoint_ops);
+						  &longjmp_breakpoint_ops, 1);
 	clone->thread = thread;
       }

@@ -7440,7 +7441,8 @@ set_longjmp_breakpoint_for_call_dummy (void)
 	struct breakpoint *new_b;

 	new_b = momentary_breakpoint_from_master (b, bp_longjmp_call_dummy,
-						  &momentary_breakpoint_ops);
+						  &momentary_breakpoint_ops,
+						  1);
 	new_b->thread = pid_to_thread_id (inferior_ptid);

 	/* Link NEW_B into the chain of RETVAL breakpoints.  */
@@ -7533,7 +7535,7 @@ set_std_terminate_breakpoint (void)
 	&& b->type == bp_std_terminate_master)
       {
 	momentary_breakpoint_from_master (b, bp_std_terminate,
-					  &momentary_breakpoint_ops);
+					  &momentary_breakpoint_ops, 1);
       }
 }

@@ -9051,13 +9053,14 @@ set_momentary_breakpoint (struct gdbarch
*gdbarch, struct symtab_and_line sal,
 }

 /* Make a momentary breakpoint based on the master breakpoint ORIG.
-   The new breakpoint will have type TYPE, and use OPS as it
-   breakpoint_ops.  */
+   The new breakpoint will have type TYPE, use OPS as its
+   breakpoint_ops, and will set enabled to LOC_ENABLED.  */

 static struct breakpoint *
 momentary_breakpoint_from_master (struct breakpoint *orig,
 				  enum bptype type,
-				  const struct breakpoint_ops *ops)
+				  const struct breakpoint_ops *ops,
+				  int loc_enabled)
 {
   struct breakpoint *copy;

@@ -9073,6 +9076,7 @@ momentary_breakpoint_from_master (struct
breakpoint *orig,
   copy->loc->probe = orig->loc->probe;
   copy->loc->line_number = orig->loc->line_number;
   copy->loc->symtab = orig->loc->symtab;
+  copy->loc->enabled = loc_enabled;
   copy->frame_id = orig->frame_id;
   copy->thread = orig->thread;
   copy->pspace = orig->pspace;
@@ -9095,7 +9099,7 @@ clone_momentary_breakpoint (struct breakpoint *orig)
   if (orig == NULL)
     return NULL;

-  return momentary_breakpoint_from_master (orig, orig->type, orig->ops);
+  return momentary_breakpoint_from_master (orig, orig->type, orig->ops, 0);
 }

 struct breakpoint *
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 47604c7..4e808d9 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -569,7 +569,9 @@ follow_inferior_reset_breakpoints (void)

   /* Was there a step_resume breakpoint?  (There was if the user
      did a "next" at the fork() call.)  If so, explicitly reset its
-     thread number.
+     thread number.  Cloned step_resume breakpoints are disabled on
+     creation, so enable it here now that it is associated with the
+     correct thread.

      step_resumes are a form of bp that are made to be per-thread.
      Since we created the step_resume bp when the parent process
@@ -579,10 +581,17 @@ follow_inferior_reset_breakpoints (void)
      it is for, or it'll be ignored when it triggers.  */

   if (tp->control.step_resume_breakpoint)
-    breakpoint_re_set_thread (tp->control.step_resume_breakpoint);
+    {
+      breakpoint_re_set_thread (tp->control.step_resume_breakpoint);
+      tp->control.step_resume_breakpoint->loc->enabled = 1;
+    }

+  /* Treat exception_resume breakpoints like step_resume breakpoints.  */
   if (tp->control.exception_resume_breakpoint)
-    breakpoint_re_set_thread (tp->control.exception_resume_breakpoint);
+    {
+      breakpoint_re_set_thread (tp->control.exception_resume_breakpoint);
+      tp->control.exception_resume_breakpoint->loc->enabled = 1;
+    }

   /* Reinsert all breakpoints in the child.  The user may have set
      breakpoints after catching the fork, in which case those
diff --git a/gdb/testsuite/gdb.base/foll-fork.exp
b/gdb/testsuite/gdb.base/foll-fork.exp
index e1201d7..ad8b750 100644
--- a/gdb/testsuite/gdb.base/foll-fork.exp
+++ b/gdb/testsuite/gdb.base/foll-fork.exp
@@ -53,60 +53,130 @@ proc check_fork_catchpoints {} {
   }
 }

-proc default_fork_parent_follow {} {
+# Test follow-fork to ensure that the correct process is followed, that
+# the followed process stops where it is expected to stop, that processes
+# are detached (or not) as expected, and that the inferior list has the
+# expected contents after following the fork.  WHO is the argument to
+# the 'set follow-fork-mode' command, DETACH is the argument to the
+# 'set detach-on-fork' command, and CMD is the GDB command used to
+# execute the program past the fork.  If the value of WHO or DETACH is
+# 'default', the corresponding GDB command is skipped for that test.
+# The value of CMD must be either 'next 2' or 'continue'.
+proc test_follow_fork { who detach cmd } {
     global gdb_prompt
+    global srcfile
+    global testfile

-    gdb_test "show follow-fork" \
-	"Debugger response to a program call of fork or vfork is \"parent\".*" \
-	"default show parent follow, no catchpoints"
+    with_test_prefix "follow $who, detach $detach, command \"$cmd\"" {

-    gdb_test "next 2" \
-	"Detaching after fork from.*" \
-	"default parent follow, no catchpoints"
+	# Start a new debugger session each time so defaults are legitimate.
+	clean_restart $testfile

-    # 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 ![runto_main] {
+	    untested "could not run to main"
+	    return -1
+	}

-proc explicit_fork_parent_follow {} {
-    global gdb_prompt
+	# The "Detaching..." and "Attaching..." messages may be hidden by
+	# default.
+	gdb_test_no_output "set verbose"

-    gdb_test_no_output "set follow-fork parent"
+	# Set follow-fork-mode if we aren't using the default.
+	if {$who == "default"} {
+	    set who "parent"
+	} else {
+	    gdb_test_no_output "set follow-fork $who"
+	}

-    gdb_test "show follow-fork" \
-	"Debugger response to a program call of fork or vfork is \"parent\"." \
-	"explicit show parent follow, no catchpoints"
+	gdb_test "show follow-fork" \
+	"Debugger response to a program call of fork or vfork is \"$who\"." \
+	"show follow-fork"

-    gdb_test "next 2" "Detaching after fork from.*" \
-	"explicit parent follow, no catchpoints"
+	# Set detach-on-fork mode if we aren't using the default.
+	if {$detach == "default"} {
+	    set detach "on"
+	} else {
+	    gdb_test_no_output "set detach-on-fork $detach"
+	}

-    # 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
-}
+	gdb_test "show detach-on-fork" \
+		 "Whether gdb will detach.* fork is $detach." \
+		 "show detach-on-fork"
+
+	# Set a breakpoint after the fork if we aren't single-stepping
+	# past the fork.
+	if {$cmd == "continue"} {
+	    set bp_after_fork [gdb_get_line_number "set breakpoint here"]
+	    gdb_test "break ${srcfile}:$bp_after_fork" \
+		     "Breakpoint.*, line $bp_after_fork.*" \
+		     "set breakpoint after fork"
+	}

-proc explicit_fork_child_follow {} {
-    global gdb_prompt
+	# Set up the output we expect to see after we run.
+	set expected_re ""
+	if {$who == "child"} {
+	    set expected_re "Attaching after.* fork to.*set breakpoint here.*"
+	} elseif {$who == "parent" && $detach == "on"} {
+	    set expected_re "Detaching after fork from .*set breakpoint here.*"
+	} else {
+	    set expected_re ".*set breakpoint here.*"
+	}

-    gdb_test_no_output "set follow-fork child"
+	# Test running past and following the fork, using the parameters
+	# set above.
+	gdb_test $cmd $expected_re "$cmd past fork"

-    gdb_test "show follow-fork" \
-	"Debugger response to a program call of fork or vfork is \"child\"." \
-	"explicit show child follow, no catchpoints"
+	# Check that we have the inferiors arranged correctly after
+	# following the fork.
+	set resume_unfollowed 0
+	if {$who == "parent" && $detach == "on"} {

-    gdb_test "next 2" "Attaching after.* fork to.*" \
-	"explicit child follow, no catchpoints"
+	    # Follow parent / detach child: the only inferior is the parent.
+	    gdb_test "info inferiors" "\\* 1 .* process.*" \
+		     "info inferiors"

-    # 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
+	} elseif {$who == "parent" && $detach == "off"} {
+
+	    # Follow parent / keep child: two inferiors under debug, the
+	    # parent is the current inferior.
+	    gdb_test "info inferiors" " 2 .*process.*\\* 1 .*process.*" \
+		     "info inferiors"
+
+	    gdb_test "inferior 2" "Switching to inferior 2 .*"
+	    set resume_unfollowed 1
+
+	} elseif {$who == "child" && $detach == "on"} {
+
+	    # Follow child / detach parent: the child is under debug and is
+	    # the current inferior.  The parent is listed but is not under
+	    # debug.
+	    gdb_test "info inferiors" "\\* 2 .*process.* 1 .*<null>.*" \
+		     "info inferiors"
+
+	} elseif {$who == "child" && $detach == "off"} {
+
+	    # Follow child / keep parent: two inferiors under debug, the
+	    # child is the current inferior.
+	    gdb_test "info inferiors" "\\* 2 .*process.* 1 .*process.*" \
+		     "info inferiors"
+
+	    gdb_test "inferior 1" "Switching to inferior 1 .*"
+	    set resume_unfollowed 1
+	}
+
+	if {$resume_unfollowed == 1} {
+	    if {$cmd == "next 2"} {
+
+		gdb_continue_to_end "continue unfollowed inferior to end"
+
+	    } elseif {$cmd == "continue"} {
+
+		gdb_continue_to_breakpoint \
+		    "continue unfollowed inferior to bp" \
+		    ".* set breakpoint here.*"
+	    }
+	}
+    }
 }

 proc catch_fork_child_follow {} {
@@ -254,6 +324,7 @@ proc tcatch_fork_parent_follow {} {

 proc do_fork_tests {} {
     global gdb_prompt
+    global testfile

     # Verify that help is available for "set follow-fork-mode".
     #
@@ -286,31 +357,31 @@ By default, the debugger will follow the parent
process..*" \
     # fork-following is supported.
     if [runto_main] then { check_fork_catchpoints }

-    # Test the default behaviour, which is to follow the parent of a
-    # fork, and detach from the child.  Do this without catchpoints.
+    # Test the basic follow-fork functionality using all combinations of
+    # values for follow-fork-mode and detach-on-fork, using either a
+    # breakpoint or single-step to execute past the fork.
     #
-    if [runto_main] then { default_fork_parent_follow }
-
-    # Test the ability to explicitly follow the parent of a fork, and
-    # detach from the child.  Do this without catchpoints.
-    #
-    if [runto_main] then { explicit_fork_parent_follow }
+    # The first loop should be sufficient to test the defaults.  There
+    # is no need to test using the defaults in other permutations (e.g.
+    # "default" "on", "parent" "default", etc.).
+    foreach cmd {"next 2" "continue"} {
+        test_follow_fork "default" "default" $cmd
+    }

-    # Test the ability to follow the child of a fork, and detach from
-    # the parent.  Do this without catchpoints.
-    #
-    if [runto_main] then { explicit_fork_child_follow }
+    # Now test all explicit permutations.
+    foreach who {"parent" "child"} {
+	foreach detach {"on" "off"} {
+	    foreach cmd {"next 2" "continue"} {
+		test_follow_fork $who $detach $cmd
+	    }
+	}
+    }

-    # Test the ability to follow both child and parent of a fork.  Do
-    # this without catchpoints.
-    # ??rehrauer: NYI.  Will add testpoints here when implemented.
-    #
+    # Catchpoint tests.

-    # Test the ability to have the debugger ask the user at fork-time
-    # whether to follow the parent, child or both.  Do this without
-    # catchpoints.
-    # ??rehrauer: NYI.  Will add testpoints here when implemented.
-    #
+    # Restart to eliminate any effects of the follow-fork tests.
+    clean_restart $testfile
+    gdb_test_no_output "set verbose"

     # Test the ability to catch a fork, specify that the child be
