--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -1918,7 +1918,8 @@ demand_private_info (ptid_t ptid)
       info->priv = XNEW (struct private_thread_info);
       info->private_dtor = free_private_thread_info;
       info->priv->core = -1;
-      info->priv->extra = 0;
+      info->priv->extra = NULL;
+      info->priv->name = NULL;


This is now pushed; the updated patch is attached.
I think with this, basic remote fork and exec events are complete.  I
appreciate all your help with this project, Pedro.  Thanks for hanging
in there with me!
--Don

From: Don Breazeal <donb@codesourcery.com>
Subject: [pushed][PATCH v3 2/3] Target remote mode fork and exec events

This is the version of the patch that was pushed.  The only differences
from v2 are:

 * server.c:process_serial_event, use target_running instead of
   get_first_inferior
 * replace remote_kill in its original location in remote.c
 * remote.c:remote_kill, remove unreachable "return"

I also ran into an intermittent failure that was caused by an
uninitialized variable, exposed by the new functionality.  I just
included the change here as obvious:

--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -1918,7 +1918,8 @@ demand_private_info (ptid_t ptid)
       info->priv = XNEW (struct private_thread_info);
       info->private_dtor = free_private_thread_info;
       info->priv->core = -1;
-      info->priv->extra = 0;
+      info->priv->extra = NULL;
+      info->priv->name = NULL;

Here is the commit message:

This patch implements support for fork and exec events with target remote
mode Linux targets.  For such targets with Linux kernels 2.5.46 and later,
this enables follow-fork-mode, detach-on-fork and fork and exec
catchpoints.

The changes required to implement this included:

 * Don't exit from gdbserver if there are still active inferiors.

 * Allow changing the active process in remote mode.

 * Enable fork and exec events in remote mode.

 * Print "Ending remote debugging" only when disconnecting.

 * Combine remote_kill and extended_remote_kill into a single function
   that can handle the multiple inferior case for target remote.  Also,
   the same thing for remote_mourn and extended_remote_mourn.

 * Enable process-style ptids in target remote.

 * Remove restriction on multiprocess mode in target remote.

gdb/gdbserver/ChangeLog:

	* server.c (process_serial_event): Don't exit from gdbserver
	in remote mode if there are still active inferiors.

gdb/ChangeLog:

	* inferior.c (number_of_live_inferiors): New function.
	(have_live_inferiors): Use number_of_live_inferiors in place
	of duplicate code.
	* inferior.h (number_of_live_inferiors): Declare new function.
	* remote.c (set_general_process): Remove restriction on target
	remote mode.
	(remote_query_supported): Likewise.
	(remote_detach_1): Exit in target remote mode only when there
	is just one live inferior left.
	(remote_disconnect): Unpush the target directly instead of
	calling remote_mourn.
	(remote_kill): Rewrite function to handle both target remote
	and extended-remote.  Call remote_kill_k.
	(remote_kill_k): New function.
	(extended_remote_kill): Delete function.
	(remote_mourn, extended_remote_mourn): Combine functions into
	one, remote_mourn, and enable extended functionality for target
	remote.
	(remote_pid_to_str): Enable "process" style ptid string for
	target remote.
	(remote_supports_multi_process): Remove restriction on target
	remote mode.

---
 gdb/ChangeLog           |  25 ++++++
 gdb/gdbserver/ChangeLog |   5 ++
 gdb/gdbserver/server.c  |   6 +-
 gdb/inferior.c          |  31 ++++++--
 gdb/inferior.h          |   3 +
 gdb/remote.c            | 205
+++++++++++++++++++++++-------------------------
 6 files changed, 161 insertions(+), 114 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index f9ed66d..9ded377 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,28 @@
+2015-12-11  Don Breazeal  <donb@codesourcery.com>
+
+	* inferior.c (number_of_live_inferiors): New function.
+	(have_live_inferiors): Use number_of_live_inferiors in place
+	of duplicate code.
+	* inferior.h (number_of_live_inferiors): Declare new function.
+	* remote.c (set_general_process): Remove restriction on target
+	remote mode.
+	(remote_query_supported): Likewise.
+	(remote_detach_1): Exit in target remote mode only when there
+	is just one live inferior left.
+	(remote_disconnect): Unpush the target directly instead of
+	calling remote_mourn.
+	(remote_kill): Rewrite function to handle both target remote
+	and extended-remote.  Call remote_kill_k.
+	(remote_kill_k): New function.
+	(extended_remote_kill): Delete function.
+	(remote_mourn, extended_remote_mourn): Combine functions into
+	one, remote_mourn, and enable extended functionality for target
+	remote.
+	(remote_pid_to_str): Enable "process" style ptid string for
+	target remote.
+	(remote_supports_multi_process): Remove restriction on target
+	remote mode.
+
 2015-12-14  Andrew Burgess  <andrew.burgess@embecosm.com>

 	* i386-tdep.c (i386_mpx_info_bounds): Use TYPE_LENGTH.
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 617c249..63bb250 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,8 @@
+2015-12-11  Don Breazeal  <donb@codesourcery.com>
+
+	* server.c (process_serial_event): Don't exit from gdbserver
+	in remote mode if there are still active inferiors.
+
 2015-12-11  Yao Qi  <yao.qi@linaro.org>

 	* linux-aarch64-low.c (aarch64_breakpoint_at): Call
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index a09841c..8f097e5 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -3959,9 +3959,11 @@ process_serial_event (void)
 	  discard_queued_stop_replies (pid_to_ptid (pid));
 	  write_ok (own_buf);

-	  if (extended_protocol)
+	  if (extended_protocol || target_running ())
 	    {
-	      /* Treat this like a normal program exit.  */
+	      /* There is still at least one inferior remaining or
+		 we are in extended mode, so don't terminate gdbserver,
+		 and instead treat this like a normal program exit.  */
 	      last_status.kind = TARGET_WAITKIND_EXITED;
 	      last_status.value.integer = 0;
 	      last_ptid = pid_to_ptid (pid);
diff --git a/gdb/inferior.c b/gdb/inferior.c
index 157e236..a0296c8 100644
--- a/gdb/inferior.c
+++ b/gdb/inferior.c
@@ -459,22 +459,41 @@ have_inferiors (void)
   return 0;
 }

+/* Return the number of live inferiors.  We account for the case
+   where an inferior might have a non-zero pid but no threads, as
+   in the middle of a 'mourn' operation.  */
+
 int
-have_live_inferiors (void)
+number_of_live_inferiors (void)
 {
   struct inferior *inf;
+  int num_inf = 0;

   for (inf = inferior_list; inf; inf = inf->next)
     if (inf->pid != 0)
       {
 	struct thread_info *tp;
-	
-	tp = any_thread_of_process (inf->pid);
-	if (tp && target_has_execution_1 (tp->ptid))
-	  break;
+
+	ALL_NON_EXITED_THREADS (tp)
+	 if (tp && ptid_get_pid (tp->ptid) == inf->pid)
+	   if (target_has_execution_1 (tp->ptid))
+	     {
+	       /* Found a live thread in this inferior, go to the next
+		  inferior.  */
+	       ++num_inf;
+	       break;
+	     }
       }

-  return inf != NULL;
+  return num_inf;
+}
+
+/* Return true if there is at least one live inferior.  */
+
+int
+have_live_inferiors (void)
+{
+  return number_of_live_inferiors () > 0;
 }

 /* Prune away any unused inferiors, and then prune away no longer used
diff --git a/gdb/inferior.h b/gdb/inferior.h
index d3cf615..78a5ed3 100644
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -490,6 +490,9 @@ extern struct inferior *iterate_over_inferiors (int
(*) (struct inferior *,
 /* Returns true if the inferior list is not empty.  */
 extern int have_inferiors (void);

+/* Returns the number of live inferiors (real live processes).  */
+extern int number_of_live_inferiors (void);
+
 /* Returns true if there are any live inferiors in the inferior list
    (not cores, not executables, real live processes).  */
 extern int have_live_inferiors (void);
diff --git a/gdb/remote.c b/gdb/remote.c
index 52c5df8..1190522 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -119,12 +119,12 @@ struct remote_state;

 static int remote_vkill (int pid, struct remote_state *rs);

+static void remote_kill_k (void);
+
 static void remote_mourn (struct target_ops *ops);

 static void extended_remote_restart (void);

-static void extended_remote_mourn (struct target_ops *);
-
 static void remote_send (char **buf, long *sizeof_buf_p);

 static int readchar (int timeout);
@@ -1918,7 +1918,8 @@ demand_private_info (ptid_t ptid)
       info->priv = XNEW (struct private_thread_info);
       info->private_dtor = free_private_thread_info;
       info->priv->core = -1;
-      info->priv->extra = 0;
+      info->priv->extra = NULL;
+      info->priv->name = NULL;
     }

   return info->priv;
@@ -2097,7 +2098,7 @@ set_general_process (void)
   struct remote_state *rs = get_remote_state ();

   /* If the remote can't handle multiple processes, don't bother.  */
-  if (!rs->extended || !remote_multi_process_p (rs))
+  if (!remote_multi_process_p (rs))
     return;

   /* We only need to change the remote current thread if it's pointing
@@ -4609,18 +4610,15 @@ remote_query_supported (void)

       q = remote_query_supported_append (q, "qRelocInsn+");

-      if (rs->extended)
-	{
-	  if (packet_set_cmd_state (PACKET_fork_event_feature)
-	      != AUTO_BOOLEAN_FALSE)
-	    q = remote_query_supported_append (q, "fork-events+");
-	  if (packet_set_cmd_state (PACKET_vfork_event_feature)
-	      != AUTO_BOOLEAN_FALSE)
-	    q = remote_query_supported_append (q, "vfork-events+");
-	  if (packet_set_cmd_state (PACKET_exec_event_feature)
-	      != AUTO_BOOLEAN_FALSE)
-	    q = remote_query_supported_append (q, "exec-events+");
-	}
+      if (packet_set_cmd_state (PACKET_fork_event_feature)
+	  != AUTO_BOOLEAN_FALSE)
+	q = remote_query_supported_append (q, "fork-events+");
+      if (packet_set_cmd_state (PACKET_vfork_event_feature)
+	  != AUTO_BOOLEAN_FALSE)
+	q = remote_query_supported_append (q, "vfork-events+");
+      if (packet_set_cmd_state (PACKET_exec_event_feature)
+	  != AUTO_BOOLEAN_FALSE)
+	q = remote_query_supported_append (q, "exec-events+");

       if (packet_set_cmd_state (PACKET_vContSupported) !=
AUTO_BOOLEAN_FALSE)
