diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 66b1729..eabf262 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -419,8 +419,8 @@ handle_extended_wait (struct lwp_info *event_child, int wstat)
 
 	  if (debug_threads)
 	    {
-	      debug_printf ("HEW: Got fork event from LWP %ld, "
-			    "new child is %d\n",
+	      debug_printf ("HEW: Got fork event "
+			    "from LWP %ld, new child is %d\n",
 			    ptid_get_lwp (ptid_of (event_thr)),
 			    ptid_get_pid (ptid));
 	    }
@@ -1045,6 +1045,24 @@ linux_kill (int pid)
 {
   struct process_info *process;
   struct lwp_info *lwp;
+  struct target_waitstatus last;
+  ptid_t last_ptid;
+
+  /* If we're stopped while forking and we haven't followed yet,
+     kill the child task.  We need to do this first because the
+     parent will be sleeping if this is a vfork.  */
+
+  get_last_target_status (&last_ptid, &last);
+
+  if (last.kind == TARGET_WAITKIND_FORKED
+      || last.kind == TARGET_WAITKIND_VFORKED)
+    {
+      lwp = find_lwp_pid (last.value.related_pid);
+      gdb_assert (lwp != NULL);
+      kill_wait_lwp (lwp);
+      process = find_process_pid (ptid_get_pid (last.value.related_pid));
+      the_target->mourn (process);
+    }
 
   process = find_process_pid (pid);
   if (process == NULL)
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index 57190f6..f525d3e 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -1301,6 +1301,15 @@ handle_qxfer_threads_worker (struct inferior_list_entry *inf, void *arg)
   int core = target_core_of_thread (ptid);
   char core_s[21];
 
+  /* Skip new threads created as the result of a fork if we are not done
+     handling that fork event.  We won't know whether to tell GDB about
+     the new thread until we are done following the fork.  */
+  if ((last_status.kind == TARGET_WAITKIND_FORKED
+       || last_status.kind == TARGET_WAITKIND_VFORKED)
+      && (ptid_get_pid (last_status.value.related_pid)
+	  == ptid_get_pid (ptid)))
+    return;
+
   write_ptid (ptid_s, ptid);
 
   if (core != -1)
@@ -3992,3 +4001,12 @@ handle_target_event (int err, gdb_client_data client_data)
 
   return 0;
 }
+
+/* Retrieve the last waitstatus reported to GDB.  */
+
+void
+get_last_target_status (ptid_t *ptid, struct target_waitstatus *last)
+{
+  *ptid = last_ptid;
+  *last = last_status;
+}
diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h
index 5284dac..86e584e 100644
--- a/gdb/gdbserver/server.h
+++ b/gdb/gdbserver/server.h
@@ -102,6 +102,8 @@ typedef int gdb_fildes_t;
 /* Functions from server.c.  */
 extern int handle_serial_event (int err, gdb_client_data client_data);
 extern int handle_target_event (int err, gdb_client_data client_data);
+extern void get_last_target_status (ptid_t *ptid,
+				    struct target_waitstatus *last);
 
 #include "remote-utils.h"
 
diff --git a/gdb/remote.c b/gdb/remote.c
index 6ea3c60..d59309f 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -1449,7 +1449,6 @@ remote_fork_event_p (struct remote_state *rs)
   return packet_support (PACKET_fork_event_feature) == PACKET_ENABLE;
 }
 
-#if PTRACE_FORK_EVENTS
 /* Returns true if vfork events are supported.  */
 
 static int
@@ -1457,7 +1456,7 @@ remote_vfork_event_p (struct remote_state *rs)
 {
   return packet_support (PACKET_vfork_event_feature) == PACKET_ENABLE;
 }
-#endif
+
 
 /* Target follow-fork function for remote targets.  On entry, and
    at return, the current inferior is the fork parent.
@@ -1509,6 +1508,46 @@ remote_follow_fork (struct target_ops *target, int follow_child,
   return 0;
 }
 
+/* Insert fork catchpoint target routine.  If fork events are enabled
+   then return success, nothing more to do.  */
+
+static int
+remote_insert_fork_catchpoint (struct target_ops *ops, int pid)
+{
+  struct remote_state *rs = get_remote_state ();
+
+  return !remote_fork_event_p (rs);
+}
+
+/* Remove fork catchpoint target routine.  Nothing to do, just
+   return success.  */
+
+static int
+remote_remove_fork_catchpoint (struct target_ops *ops, int pid)
+{
+  return 0;
+}
+
+/* Insert vfork catchpoint target routine.  If vfork events are enabled
+   then return success, nothing more to do.  */
+
+static int
+remote_insert_vfork_catchpoint (struct target_ops *ops, int pid)
+{
+  struct remote_state *rs = get_remote_state ();
+
+  return !remote_vfork_event_p (rs);
+}
+
+/* Remove vfork catchpoint target routine.  Nothing to do, just
+   return success.  */
+
+static int
+remote_remove_vfork_catchpoint (struct target_ops *ops, int pid)
+{
+  return 0;
+}
+
 /* Tokens for use by the asynchronous signal handlers for SIGINT.  */
 static struct async_signal_handler *async_sigint_remote_twice_token;
 static struct async_signal_handler *async_sigint_remote_token;
@@ -11766,6 +11805,10 @@ Specify the serial device it is connected to\n\
   remote_ops.to_augmented_libraries_svr4_read =
     remote_augmented_libraries_svr4_read;
   remote_ops.to_follow_fork = remote_follow_fork;
+  remote_ops.to_insert_fork_catchpoint = remote_insert_fork_catchpoint;
+  remote_ops.to_remove_fork_catchpoint = remote_remove_fork_catchpoint;
+  remote_ops.to_insert_vfork_catchpoint = remote_insert_vfork_catchpoint;
+  remote_ops.to_remove_vfork_catchpoint = remote_remove_vfork_catchpoint;
 }
 
 /* Set up the extended remote vector by making a copy of the standard
diff --git a/gdb/testsuite/gdb.base/foll-fork.exp b/gdb/testsuite/gdb.base/foll-fork.exp
index 3f2d224..697570d 100644
--- a/gdb/testsuite/gdb.base/foll-fork.exp
+++ b/gdb/testsuite/gdb.base/foll-fork.exp
@@ -13,8 +13,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-if { [is_remote target] || ![isnative] } then {
-    continue
+if {![isnative]} then {
+    return 0
 }
 
 # Until "set follow-fork-mode" and "catch fork" are implemented on
diff --git a/gdb/testsuite/gdb.base/foll-vfork.exp b/gdb/testsuite/gdb.base/foll-vfork.exp
index 78c5cc8..ec8db33 100644
--- a/gdb/testsuite/gdb.base/foll-vfork.exp
+++ b/gdb/testsuite/gdb.base/foll-vfork.exp
@@ -18,8 +18,8 @@
 # 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
+if {![isnative]} then {
+    return 0
 }
 
 # Until "set follow-fork-mode" and "catch vfork" are implemented on
diff --git a/gdb/testsuite/gdb.threads/fork-child-threads.exp b/gdb/testsuite/gdb.threads/fork-child-threads.exp
index 75e60e1..3815c92 100644
--- a/gdb/testsuite/gdb.threads/fork-child-threads.exp
+++ b/gdb/testsuite/gdb.threads/fork-child-threads.exp
@@ -13,12 +13,12 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-# Only GNU/Linux is known to support `set follow-fork-mode child'.
-if { ! [istarget "*-*-linux*"] } {
+if {![isnative] } then {
     return 0
 }
 
-if { [is_remote target] || ![isnative] } then {
+# Only GNU/Linux is known to support `set follow-fork-mode child'.
+if { ! [istarget "*-*-linux*"] } {
     return 0
 }
 
diff --git a/gdb/testsuite/gdb.threads/fork-thread-pending.exp b/gdb/testsuite/gdb.threads/fork-thread-pending.exp
index d229232..bbd980a 100644
--- a/gdb/testsuite/gdb.threads/fork-thread-pending.exp
+++ b/gdb/testsuite/gdb.threads/fork-thread-pending.exp
@@ -13,9 +13,7 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-# There's no support for `set follow-fork-mode' in the remote
-# protocol.
-if { [is_remote target] } {
+if {![isnative]} {
     return 0
 }
 
@@ -31,6 +29,26 @@ if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executab
     return -1
 }
 
+# Find a thread that did not fork and is not the main thread and
+# return its thread number.  We can't just hard-code the thread
+# number since we have no guarantee as to the ordering of the threads
+# in gdb.  We know that the main thread is in pthread_join and the
+# forking thread is in fork, so we use this rather ungainly regexp
+# to capture an entry from 'info threads' that doesn't show one of
+# those routines, then extract the thread number.
+
+proc find_unforked_thread { } {
+    gdb_test_multiple "info threads" "find unforked thread" {
+        -re "(\[^\r]*Thread\[^\r]* in \[^fp]\[^ot]\[^rh]\[^kr]\[^e]\[^a]\[^d]\[^_]\[^j]\[^\r]*\r\n)" {
+    	    regexp "(\[ 	]*)(\[0-9]*)(\[    ]*Thread\[^\r]*\r\n)" $expect_out(0,string) ignore lead_spc threadnum rest
+        }
+        timeout {
+	    set threadnum -1
+        }
+    }
+    return $threadnum
+}
+
 clean_restart ${binfile}
 
 if ![runto_main] then {
@@ -46,7 +64,8 @@ gdb_test "continue" "Catchpoint.*" "1, get to the fork event"
 
 gdb_test "info threads" " Thread .* Thread .* Thread .* Thread .*" "1, multiple threads found"
 
-gdb_test "thread 1" ".*" "1, switched away from event thread"
+set threadnum [find_unforked_thread]
+gdb_test "thread $threadnum" ".*" "1, switched away from event thread to thread $threadnum"
 
 gdb_test "continue" "Not resuming.*" "1, refused to resume"
 
diff --git a/gdb/testsuite/gdb.threads/watchpoint-fork.exp b/gdb/testsuite/gdb.threads/watchpoint-fork.exp
index a4557f8..a1dbd10 100644
--- a/gdb/testsuite/gdb.threads/watchpoint-fork.exp
+++ b/gdb/testsuite/gdb.threads/watchpoint-fork.exp
@@ -17,9 +17,8 @@
 
 set testfile watchpoint-fork
 
-if [is_remote target] {
-    kfail "remote/13584" "gdbserver does not support debugging across fork"
-    return
+if {![isnative]} {
+    return 0
 }
 
 proc test {type symbol} {
