diff --git a/event-loop.c b/event-loop.c
index a3310a05c8b..eddbbcdfa5f 100644
--- a/event-loop.c
+++ b/event-loop.c
@@ -19,6 +19,7 @@
  /* Based on src/gdb/event-loop.c.  */

  #include "server.h"
+#include "remote-utils.h"

  #include <sys/types.h>
  #include "gdb_sys_time.h"
@@ -375,7 +376,11 @@ delete_file_handler (gdb_fildes_t fd)
  	;
        prev_ptr->next_file = file_ptr->next_file;
      }
-  free (file_ptr);
+
+  /* Do not free in case another client tries to attach */
+  /* free (file_ptr); */
+  struct multi_client_states & client_states = get_client_states();
+  client_states.delete_client_state (fd);
  }

  /* Handle the given event by calling the procedure associated to the
@@ -415,6 +420,12 @@ handle_file_event (gdb_fildes_t event_file_desc)
  	  /* If there was a match, then call the handler.  */
  	  if (mask != 0)
  	    {
+	      /* Switch client states if we have multiple clients */
+	      if (have_multiple_clients (file_ptr->fd))
+		{
+		  struct multi_client_states & client_states = get_client_states();
+		  client_states.set_client_state (file_ptr->fd);
+		}
  	      if ((*file_ptr->proc) (file_ptr->error,
  				     file_ptr->client_data) < 0)
  		return -1;
@@ -455,6 +466,37 @@ wait_for_event (void)
    file_handler *file_ptr;
    int num_found = 0;

+  /* Do we have another client? */
+  fd_set conn_fd_set;
+  struct timeval timeout;
+  FD_ZERO(&conn_fd_set);
+  FD_SET(get_listen_desc(),&conn_fd_set);
+  timeout.tv_sec = 0;
+  timeout.tv_usec = 10;
+  num_found = select (FD_SETSIZE, &conn_fd_set, NULL, NULL, &timeout);
+  if (debug_threads > 1)
+    fprintf (stderr,"%s select fd=%d 
found=%d\n",__FUNCTION__,get_listen_desc(),num_found);
+  if (num_found > 0)
+    {
+    int i;
+      for (i = 1; i < FD_SETSIZE; ++i)
+	if (FD_ISSET (i, &conn_fd_set))
+	  {
+	    if (i == get_listen_desc())
+	      {
+		client_state &cs = get_client_state();
+		if (debug_threads > 1)
+		  fprintf (stderr,"%s in select idx %d\n",__FUNCTION__,i);
+		/* instead of using gdb_event just setup the connection "by hand" */
+		handle_accept_event (0, NULL);
+		add_file_handler (get_remote_desc(), handle_serial_event, &cs);
+	      }
+	    else
+	      if (debug_threads > 1)
+		fprintf (stderr,"%s data arrived on existing connection %d fd=%d\n", 
__FUNCTION__, i,get_listen_desc());
+	  }
+    }
+
    /* Make sure all output is done before getting another event.  */
    fflush (stdout);
    fflush (stderr);
diff --git a/linux-low.c b/linux-low.c
index 701f3e863c0..7f78b7a39fd 100644
--- a/linux-low.c
+++ b/linux-low.c
@@ -3084,6 +3084,9 @@ gdb_catch_this_syscall_p (struct lwp_info 
*event_child)
    if (proc->syscalls_to_catch.empty ())
      return 0;

+  if (proc->syscalls_to_catch[0] == NO_SYSCALL)
+    return 0;
+
    if (proc->syscalls_to_catch[0] == ANY_SYSCALL)
      return 1;

diff --git a/notif.c b/notif.c
index 5ff7079123f..42ef793f255 100644
--- a/notif.c
+++ b/notif.c
@@ -67,6 +67,7 @@ notif_write_event (struct notif_server *notif, char 
*own_buf)
  	= QUEUE_peek (notif_event_p, notif->queue);

        notif->write (event, own_buf);
+      notify_clients (own_buf, 0);
      }
    else
      write_ok (own_buf);
@@ -150,7 +151,8 @@ notif_push (struct notif_server *np, struct 
notif_event *new_event)
        p += strlen (p);

        np->write (new_event, p);
-      putpkt_notif (buf);
+      if (notify_clients (buf, 1))
+	putpkt_notif (buf);
      }
  }

diff --git a/remote-utils.c b/remote-utils.c
index 9199a9c7add..15a8b5cf337 100644
--- a/remote-utils.c
+++ b/remote-utils.c
@@ -94,7 +94,7 @@ enum {
     Either NOT_SCHEDULED or the callback id.  */
  static int readchar_callback = NOT_SCHEDULED;

-static int readchar (void);
+static int readchar (gdb_fildes_t);
  static void reset_readchar (void);
  static void reschedule (void);

@@ -123,6 +123,25 @@ extern int debug_threads;
  # define write(fd, buf, len) send (fd, (char *) buf, len, 0)
  #endif

+
+int
+get_remote_desc (void)
+{
+  return remote_desc;
+}
+
+void
+set_remote_desc (gdb_fildes_t fd)
+{
+  remote_desc = fd;
+}
+
+int
+get_listen_desc (void)
+{
+  return listen_desc;
+}
+
  int
  gdb_connected (void)
  {
@@ -151,7 +170,7 @@ enable_async_notification (int fd)
  #endif
  }

-static int
+int
  handle_accept_event (int err, gdb_client_data client_data)
  {
    struct sockaddr_storage sockaddr;
@@ -164,6 +183,10 @@ handle_accept_event (int err, gdb_client_data 
client_data)
    if (remote_desc == -1)
      perror_with_name ("Accept failed");

+  struct multi_client_states & client_states = get_client_states();
+  client_state *cs = client_states.set_client_state (remote_desc);
+  cs->noack_mode = 0;
+
    /* Enable TCP keep alive process. */
    socklen_t tmp = 1;
    setsockopt (remote_desc, SOL_SOCKET, SO_KEEPALIVE,
@@ -180,7 +203,8 @@ handle_accept_event (int err, gdb_client_data 
client_data)
  				   exits when the remote side dies.  */
  #endif

-  if (run_once)
+  /* Do not close in case another client tries to attach */
+  if (0 && run_once)
      {
  #ifndef USE_WIN32API
        close (listen_desc);		/* No longer need this */
@@ -191,7 +215,8 @@ handle_accept_event (int err, gdb_client_data 
client_data)

    /* Even if !RUN_ONCE no longer notice new connections.  Still keep the
       descriptor open for add_file_handler to wait for a new 
connection.  */
-  delete_file_handler (listen_desc);
+  /* Do not delete in case another client tries to attach */
+  /*  delete_file_handler (listen_desc); */

    /* Convert IP address to string.  */
    char orig_host[GDB_NI_MAX_ADDR], orig_port[GDB_NI_MAX_PORT];
@@ -219,7 +244,9 @@ handle_accept_event (int err, gdb_client_data 
client_data)
       try to send vStopped notifications to GDB.  But, don't do that
       until GDB as selected all-stop/non-stop, and has queried the
       threads' status ('?').  */
-  target_async (0);
+
+  /* Do not async in case another client tries to attach */
+  /* target_async (0); */

    return 0;
  }
@@ -615,12 +642,12 @@ read_ptid (const char *buf, const char **obuf)
     This may return less than COUNT.  */

  static int
-write_prim (const void *buf, int count)
+write_prim (gdb_fildes_t fd, const void *buf, int count)
  {
    if (remote_connection_is_stdio ())
      return write (fileno (stdout), buf, count);
    else
-    return write (remote_desc, buf, count);
+    return write (fd, buf, count);
  }

  /* Read COUNT bytes from the client and store in BUF.
@@ -628,12 +655,12 @@ write_prim (const void *buf, int count)
     This may return less than COUNT.  */

  static int
-read_prim (void *buf, int count)
+read_prim (gdb_fildes_t fd, void *buf, int count)
  {
    if (remote_connection_is_stdio ())
      return read (fileno (stdin), buf, count);
    else
-    return read (remote_desc, buf, count);
+    return read (fd, buf, count);
  }

  /* Send a packet to the remote machine, with error checking.
@@ -674,7 +701,7 @@ putpkt_binary_1 (char *buf, int cnt, int is_notif)

    do
      {
-      if (write_prim (buf2, p - buf2) != p - buf2)
+      if (write_prim (cs.file_desc, buf2, p - buf2) != p - buf2)
  	{
  	  perror ("putpkt(write)");
  	  free (buf2);
@@ -687,21 +714,21 @@ putpkt_binary_1 (char *buf, int cnt, int is_notif)
  	  if (remote_debug)
  	    {
  	      if (is_notif)
-		debug_printf ("putpkt (\"%s\"); [notif]\n", buf2);
+	  	debug_printf ("putpkt/%d (\"%s\"); [notif]\n", cs.file_desc, buf2);
  	      else
-		debug_printf ("putpkt (\"%s\"); [noack mode]\n", buf2);
-	      debug_flush ();
+		debug_printf ("putpkt/%d (\"%s\"); [noack mode]\n", cs.file_desc, buf2);
+	      fflush (stderr);
  	    }
  	  break;
  	}

        if (remote_debug)
  	{
-	  debug_printf ("putpkt (\"%s\"); [looking for ack]\n", buf2);
-	  debug_flush ();
+	  debug_printf ("putpkt/%d (\"%s\"); [looking for ack]\n", 
cs.file_desc, buf2);
+	  fflush (stderr);
  	}

-      cc = readchar ();
+      cc = readchar (cs.file_desc);

        if (cc < 0)
  	{
@@ -769,7 +796,7 @@ input_interrupt (int unused)
        int cc;
        char c = 0;

-      cc = read_prim (&c, 1);
+      cc = read_prim (remote_desc, &c, 1);

        if (cc == 0)
  	{
@@ -899,13 +926,13 @@ static unsigned char *readchar_bufp;
  /* Returns next char from remote GDB.  -1 if error.  */

  static int
-readchar (void)
+readchar (gdb_fildes_t fd)
  {
    int ch;

    if (readchar_bufcnt == 0)
      {
-      readchar_bufcnt = read_prim (readchar_buf, sizeof (readchar_buf));
+      readchar_bufcnt = read_prim (fd, readchar_buf, sizeof 
(readchar_buf));

        if (readchar_bufcnt <= 0)
  	{
@@ -974,7 +1001,7 @@ reschedule (void)
     and store it in BUF.  Returns length of packet, or negative if 
error. */

  int
-getpkt (char *buf)
+getpkt (gdb_fildes_t fd, char *buf)
  {
    client_state &cs = get_client_state ();
    char *bp;
@@ -987,7 +1014,7 @@ getpkt (char *buf)

        while (1)
  	{
-	  c = readchar ();
+	  c = readchar (fd);

  	  /* The '\003' may appear before or after each packet, so
  	     check for an input interrupt.  */
@@ -1012,7 +1039,7 @@ getpkt (char *buf)
        bp = buf;
        while (1)
  	{
-	  c = readchar ();
+	  c = readchar (fd);
  	  if (c < 0)
  	    return -1;
  	  if (c == '#')
@@ -1022,8 +1049,8 @@ getpkt (char *buf)
  	}
        *bp = 0;

-      c1 = fromhex (readchar ());
-      c2 = fromhex (readchar ());
+      c1 = fromhex (readchar (fd));
+      c2 = fromhex (readchar (fd));

        if (csum == (c1 << 4) + c2)
  	break;
@@ -1040,7 +1067,7 @@ getpkt (char *buf)

        fprintf (stderr, "Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n",
  	       (c1 << 4) + c2, csum, buf);
-      if (write_prim ("-", 1) != 1)
+      if (write_prim (fd, "-", 1) != 1)
  	return -1;
      }

@@ -1048,11 +1075,11 @@ getpkt (char *buf)
      {
        if (remote_debug)
  	{
-	  debug_printf ("getpkt (\"%s\");  [sending ack] \n", buf);
-	  debug_flush ();
+	  debug_printf ("getpkt/%d (\"%s\");  [sending ack] \n", fd, buf);
+	  fflush (stderr);
  	}

-      if (write_prim ("+", 1) != 1)
+      if (write_prim (fd, "+", 1) != 1)
  	return -1;

        if (remote_debug)
@@ -1065,8 +1092,8 @@ getpkt (char *buf)
      {
        if (remote_debug)
  	{
-	  debug_printf ("getpkt (\"%s\");  [no ack sent] \n", buf);
-	  debug_flush ();
+	  debug_printf ("getpkt/%d (\"%s\");  [no ack sent] \n", fd, buf);
+	  fflush (stderr);
  	}
      }

@@ -1082,7 +1109,7 @@ getpkt (char *buf)
    while (readchar_bufcnt > 0 && *readchar_bufp == '\003')
      {
        /* Consume the interrupt character in the buffer.  */
-      readchar ();
+      readchar (fd);
        (*the_target->request_interrupt) ();
      }

@@ -1518,7 +1555,7 @@ look_up_one_symbol (const char *name, CORE_ADDR 
*addrp, int may_ask_gdb)
      return -1;

    /* FIXME:  Eventually add buffer overflow checking (to getpkt?)  */
-  len = getpkt (cs.own_buf);
+  len = getpkt (cs.file_desc, cs.own_buf);
    if (len < 0)
      return -1;

@@ -1556,7 +1593,7 @@ look_up_one_symbol (const char *name, CORE_ADDR 
*addrp, int may_ask_gdb)
  	}
        else
  	break;
-      len = getpkt (cs.own_buf);
+      len = getpkt (cs.file_desc, cs.own_buf);
        if (len < 0)
  	return -1;
      }
@@ -1614,7 +1651,7 @@ relocate_instruction (CORE_ADDR *to, CORE_ADDR oldloc)
      return -1;

    /* FIXME:  Eventually add buffer overflow checking (to getpkt?)  */
-  len = getpkt (cs.own_buf);
+  len = getpkt (cs.file_desc, cs.own_buf);
    if (len < 0)
      return -1;

@@ -1657,7 +1694,7 @@ relocate_instruction (CORE_ADDR *to, CORE_ADDR oldloc)
        free (mem_buf);
        if (putpkt (cs.own_buf) < 0)
  	return -1;
-      len = getpkt (cs.own_buf);
+      len = getpkt (cs.file_desc, cs.own_buf);
        if (len < 0)
  	return -1;
      }
diff --git a/remote-utils.h b/remote-utils.h
index fcd3b3a93de..94a037f0597 100644
--- a/remote-utils.h
+++ b/remote-utils.h
@@ -19,6 +19,10 @@
  #ifndef REMOTE_UTILS_H
  #define REMOTE_UTILS_H

+int get_remote_desc (void);
+void set_remote_desc (gdb_fildes_t);
+int get_listen_desc (void);
+
  extern int remote_debug;

  int gdb_connected (void);
@@ -32,7 +36,8 @@ char *write_ptid (char *buf, ptid_t ptid);
  int putpkt (char *buf);
  int putpkt_binary (char *buf, int len);
  int putpkt_notif (char *buf);
-int getpkt (char *buf);
+int getpkt (gdb_fildes_t,char *buf);
+int handle_accept_event (int err, gdb_client_data client_data);
  void remote_prepare (const char *name);
  void remote_open (const char *name);
  void remote_close (void);
diff --git a/server.c b/server.c
index 4ec3548d644..14d15c0fb85 100644
--- a/server.c
+++ b/server.c
@@ -36,6 +36,8 @@
  #include "dll.h"
  #include "hostio.h"
  #include <vector>
+#include <map>
+#include <string>
  #include "common-inferior.h"
  #include "job-control.h"
  #include "environ.h"
@@ -135,6 +137,8 @@ int disable_packet_qfThreadInfo;

  static unsigned char *mem_buf;

+static int attach_count;
+
  /* A sub-class of 'struct notif_event' for stop, holding information
     relative to a single stop reply.  We keep a queue of these to
     push to GDB in non-stop mode.  */
@@ -156,18 +160,940 @@ static struct btrace_config current_btrace_conf;

  DEFINE_QUEUE_P (notif_event_p);

-/* The client remote protocol state. */
+static struct multi_client_states client_states;
+
+multi_client_states&
+get_client_states (void)
+{
+  return client_states;
+}
+
+static void handle_status (char *);
+
+/* The wait state of a client */
+enum pending_types
+{none_pending, pending_waitee, pending_cont_waiter};
+static const char *pending_types_str[] = {"not-waiting","waitee","waiter"};
+
+/* The notification state of a nonstop client */
+enum nonstop_pending_types
+{no_notifier_pending, pending_notifier, pending_notified};
+static const char *nonstop_pending_types_str[] = {"", "notifier", 
"notified"};
+
+/* The packet type of a client packet */
+static const char *packet_types_str[] =
+{"other", "vContc", "vConts","vContr","vContt","vRun", "vAttach", "Hg", 
"g_or_m", "Detach",
+ "vStopped"};
+static const char *waitkind_str[] =
+{"exited", "stopped", "signalled", "loaded", "forked", "vforked", 
"execed",
+ "vfork-done", "syscall-entry", "syscall-exit", "spurious", "ignore",
+ "no-history", "not-resumed", "thread-created", "thread-exited", ""};
+
+static const char *displaced_step_str[] =
+    {"", "displaced-stepping", "displaced-stepping?"};
+
+
+/* Add a new client state for FD or return FD's client state if found */
+
+client_state *
+multi_client_states::set_client_state (gdb_fildes_t fd)
+{
+/* States:
+ * fd = -1 add initial client state
+ * fd =  F add client state for fd F
+ */
+
+  client_state *csidx, *cs;
+
+  /* add/return initial client state */
+  if (fd == -1)
+    {
+      if (client_states.cs.empty())
+	{
+	  client_states.cs[fd] = new (client_state);
+	  client_states.cs[fd]->file_desc = fd;
+	}
+      client_states.current_cs = client_states.cs[fd];
+      return client_states.cs[fd];
+    }
+
+  /* add/return client state for fd F */

-static client_state g_client_state;
+  std::map<gdb_fildes_t,client_state*>::iterator it;
+  it = client_states.cs.find(fd);
+  if (it != client_states.cs.end())
+    {
+      it->second->copy_status (*client_states.current_cs);
+      client_states.current_cs = it->second;
+      return it->second;
+    }
+  else
+    csidx = client_states.cs.rbegin()->second;
+
+  /* add client state S for fd F */
+  client_states.cs[fd] = cs = new client_state (fd, csidx);
+  cs->file_desc = fd;
+  client_states.set_current_client (cs);
+  return cs;
+}
+
+/* Return the current client state. */

  client_state &
  get_client_state ()
  {
-  client_state &cs = g_client_state;
-  return cs;
+  return client_states.get_client_state ();
+}
+
+client_state::client_state (gdb_fildes_t fd, client_state *csidx)
+{
+  file_desc = fd;
+  cont_thread = null_ptid;
+  general_thread = null_ptid;
+  new_general_thread = null_ptid;
+  multi_process = csidx->multi_process;
+  report_fork_events = csidx->report_fork_events;
+  report_vfork_events = csidx->report_vfork_events;
+  report_exec_events = csidx->report_exec_events;
+  report_thread_events = csidx->report_thread_events;
+  swbreak_feature = csidx->swbreak_feature;
+  hwbreak_feature = csidx->hwbreak_feature;
+  vCont_supported = csidx->vCont_supported;
+  disable_randomization = csidx->disable_randomization;
+  last_status = csidx->last_status;
+  last_ptid = null_ptid;
+  noack_mode = csidx->noack_mode;
+  transport_is_reliable = csidx->transport_is_reliable;
+
+  packet_type = other_packet;
+  last_packet_type = other_packet;
+  own_buf = (char*) xmalloc (PBUFSIZ + 1);
+}
+
+
+void
+client_state::copy_status (client_state &csidx)
+{
+  cont_thread = csidx.cont_thread;
+  general_thread = csidx.general_thread;
+  last_status = csidx.last_status;
+  last_ptid = csidx.last_ptid;
+}
+
+
+/* Are client CS1 and client CS2 attached to the same process?
+   i.e. do they share the same server_state? */
+
+static int
+attached_to_same_proc (client_state * cs1, client_state * cs2)
+{
+  return cs1->file_desc != -1 && cs2->file_desc != -1
+    && cs1 != cs2 /*&& cs1->ss == cs2->ss*/;
+}
+
+
+/* Dump the client state list for debugging purposes */
+
+static void dump_stop_queue(const char*,const char*);
+static void
+dump_client_state (const char *function, const char *comment)
+{
+  client_state *save_cs = client_states.current_cs;
+  client_state *cs;
+
+  if (! debug_threads)
+    return;
+
+  dump_stop_queue (function, comment);
+  debug_printf ("** client state at %s: %s\n", function, comment);
+  std::map<gdb_fildes_t,client_state*>::iterator it;
+
+  for (it = client_states.cs.begin(); it != client_states.cs.end(); ++it)
+    {
+      cs = it->second;
+      const char *last_status_kind;
+      struct regcache *regcache = NULL;
+      CORE_ADDR pc = 0;
+      int sc = 0;
+      static const char *syscall_state[] = {"","ignoring-syscalls"};
+
+      client_states.current_cs = cs;
+      if (cs->file_desc == -1)
+	continue;
+
+      if (cs->last_status.kind < (sizeof (waitkind_str) / sizeof (void*)))
+	last_status_kind = waitkind_str[cs->last_status.kind];
+      else
+	last_status_kind = "";
+      if (current_thread != NULL)
+	regcache = current_thread->regcache_data;
+      if (regcache != NULL)
+	pc = (*the_target->read_pc) (regcache);
+      if (current_thread && current_process()->syscalls_to_catch.size() 
 > 0)
+	if (current_process()->syscalls_to_catch[0] == NO_SYSCALL)
+	  sc = 1;
+      debug_printf ("  %c%d %s pc=%#lx %s %s %s %s %s %s %s\n",
+		    (save_cs == cs) ? '*' : ' ',
+		    cs->file_desc,
+		    target_pid_to_str (cs->general_thread),
+		    (long unsigned)pc,
+		    packet_types_str[cs->packet_type],
+		    packet_types_str[cs->last_packet_type],
+		    pending_types_str[cs->pending],
+		    nonstop_pending_types_str[cs->nonstop_pending],
+		    last_status_kind,
+		    displaced_step_str[cs->displaced_step],
+		    syscall_state[sc]);
+    }
+  client_states.current_cs = save_cs;
+}
+
+
+/* Add another client for PID to the 1 server -> N client list. */
+
+static int
+add_client_by_pid (int pid)
+{
+  client_state &cs = get_client_state();
+  client_state *matched_cs;
+  std::map<gdb_fildes_t,client_state*>::iterator it;
+
+  for (it = client_states.cs.begin(); it != client_states.cs.end(); ++it)
+    {
+      matched_cs = it->second;
+      if (cs.file_desc != matched_cs->file_desc
+	  && matched_cs->general_thread.pid() == pid)
+	{
+	  cs.multi_process = matched_cs->multi_process;
+	  cs.general_thread = matched_cs->general_thread;
+	  attach_count += 1;
+	  return 1;
+	}
+    }
+  return 0;
+}
+
+
+/* Return the first client state; skipping the initial state for fd -1 */
+
+static client_state*
+get_first_client (void)
+{
+  client_state *cs;
+  std::map<gdb_fildes_t,client_state*>::iterator it;
+
+  for (it = client_states.cs.begin(); it != client_states.cs.end(); ++it)
+    {
+      cs = it->second;
+      if (cs->file_desc > 0 /* && cs->attached_to_client == 1 */)
+       return cs;
+    }
+  return client_states.cs.begin()->second;
+}
+
+static gdb_fildes_t
+get_first_client_fd (void)
+{
+  client_state *cs = get_first_client ();
+  return cs->file_desc;
+}
+
+
+/* Do we have multiple clients? */
+
+bool
+have_multiple_clients (gdb_fildes_t fd)
+{
+  std::map<gdb_fildes_t,client_state*>::iterator it;
+
+  dump_client_state(__FUNCTION__, "");
+  for (it = client_states.cs.begin(); it != client_states.cs.end(); ++it)
+    {
+      if (it->first == fd)
+	return (attach_count > 0);
+    }
+  return false;
+}
+
+
+/* Remove the client state corresponding to fd */
+
+client_state&
+multi_client_states::delete_client_state (gdb_fildes_t fd)
+{
+  client_state *cs, *previous_cs = NULL;
+  std::map<gdb_fildes_t,client_state*>::iterator it;
+
+  for (it = client_states.cs.begin(); it != client_states.cs.end(); ++it)
+    {
+      cs = it->second;
+
+      if (it->first == fd)
+	{
+	  client_states.current_cs = previous_cs;
+	  free (cs->own_buf);
+	  delete (cs);
+	  attach_count -= 1;
+	  it = client_states.cs.erase (it);
+	}
+      previous_cs = cs;
+    }
+  return *client_states.current_cs;
+}
+
+
+/* Return the packet type for client packet CS */
+
+static packet_types
+get_packet_type (client_state & cs)
+{
+  char own_packet;
+  struct process_info *process;
+  client_state *csi;
+  packet_types this_packet_type = other_packet;
+
+  if (cs.own_buf)
+    own_packet = cs.own_buf[0];
+  else
+    return other_packet;
+
+  std::map<gdb_fildes_t,client_state*>::iterator it;
+
+  switch (own_packet)
+    {
+    case 'v':
+      if ((strncmp (cs.own_buf, "vCont;c", 7) == 0))
+	this_packet_type = vContc;
+      else if ((strncmp (cs.own_buf, "vCont;s", 7) == 0))
+	this_packet_type = vConts;
+      else if ((strncmp (cs.own_buf, "vCont;r", 7) == 0))
+	this_packet_type = vContr;
+      else if ((strncmp (cs.own_buf, "vCont;t", 7) == 0))
+	this_packet_type = vContt;
+      else if (strncmp (cs.own_buf, "vRun", 4) == 0)
+	this_packet_type = vRun;
+      else if (strncmp (cs.own_buf, "vAttach", 4) == 0)
+	this_packet_type = vAttach;
+      else if (strncmp (cs.own_buf, "vStopped", 4) == 0)
+	this_packet_type = vStopped;
+
+      switch (this_packet_type)
+	{
+	case vContc:
+	  for (it = client_states.cs.begin(); it != client_states.cs.end(); ++it)
+	    {
+	      csi = it->second;
+	      if (attached_to_same_proc (&cs, csi) && csi->syscall_op != 
NO_SYSCALL)
+		{
+		  process = current_process ();
+		  process->syscalls_to_catch[0] = csi->syscall_op;
+		  csi->syscall_op = NO_SYSCALL;
+		}
+	    }
+	  break;
+	case vConts:
+	  if (cs.displaced_step == maybe_displaced_step)
+	    cs.displaced_step = in_displaced_step;
+	  __attribute__ ((fallthrough));
+	case vContr:
+	  for (it = client_states.cs.begin(); it != client_states.cs.end(); ++it)
+	    {
+	      csi = it->second;
+	      /* an in process next can be thrown off by a syscall,
+		 so turn off and on around the next */
+	      if (attached_to_same_proc (&cs, csi) && csi->catch_syscalls)
+		{
+		  process = current_process ();
+		  int vec_value = process->syscalls_to_catch[0];
+		  if (vec_value != NO_SYSCALL)
+		    csi->syscall_op = vec_value;
+		  process->syscalls_to_catch[0] = NO_SYSCALL;
+		}
+	    }
+	}
+      return this_packet_type;
+
+    case 'H':
+      if (cs.own_buf[1] == 'g')
+	{
+	  client_states.current_cs->new_general_thread =
+	    read_ptid (&cs.own_buf[2], NULL);
+	  return Hg;
+	}
+      break;
+    case 'D':
+      return Detach;
+    case 'G':
+      if (non_stop && cs.displaced_step == not_displaced_step)
+	cs.displaced_step = maybe_displaced_step;
+      else if (cs.displaced_step == in_displaced_step)
+	cs.displaced_step = not_displaced_step;
+      __attribute__ ((fallthrough));
+    case 'm':
+    case 'M':
+    case 'g':
+      return g_or_m;
+    };
+  return other_packet;
  }


+static void queue_stop_reply_callback (thread_info *thread);
+
+static void
+vstop_notif_reply (struct notif_event *event, char *own_buf)
+{
+  struct vstop_notif *vstop = (struct vstop_notif *) event;
+
+  prepare_resume_reply (own_buf, vstop->ptid, &vstop->status);
+}
+
+struct notif_server notif_stop =
+  {
+    "vStopped", "Stop", NULL, vstop_notif_reply,
+  };
+
+/* Belatedly reply to client CS, which is waiting on a packet reply. */
+
+static void
+resolve_waiter (client_state *cs, client_state *waitee_cs)
+{
+  enum packet_types this_packet_type =
+    (enum packet_types)((cs->packet_type) ? cs->packet_type : 
cs->last_packet_type);
+  client_state *save_client_state;
+
+  save_client_state = client_states.current_cs;
+  client_states.set_client_state (cs->file_desc);
+  if (debug_threads)
+    {
+      debug_printf ("%s:%d fd=%d %s %s", __FUNCTION__, __LINE__,
+		    cs->file_desc, packet_types_str[this_packet_type],
+		    pending_types_str[cs->pending]);
+      if (waitee_cs)
+ 	debug_printf (" fd=%d %s %s", waitee_cs->file_desc,
+		      packet_types_str[waitee_cs->packet_type],
+		      pending_types_str[waitee_cs->pending]);
+      debug_printf ("\n");
+    }
+  switch (this_packet_type)
+    {
+    case vContc:
+      {
+	strcpy (cs->own_buf, "?");
+	if (non_stop)
+	  {
+	    debug_printf ("vContc non stop\n");
+	    if (cs->last_status.kind != TARGET_WAITKIND_EXITED)
+	      cs->nonstop_pending = pending_notifier;
+	  }
+	else if (cs->last_status.kind != TARGET_WAITKIND_EXITED)
+	  {
+	    debug_printf ("vContc all stop not exit\n");
+	    /* reply to vContc with a status */
+	    strcpy (cs->own_buf, "?");
+	    handle_status (cs->own_buf);
+	    putpkt (cs->own_buf);
+	  }
+	else if (cs->last_status.kind == TARGET_WAITKIND_EXITED)
+	  {
+	    debug_printf ("vContc all stop exit\n");
+	    /* Is this the same process we are waiting on? */
+	    if (cs->last_cont_ptid.pid() != cs->last_ptid.pid())
+	      {
+		prepare_resume_reply (cs->own_buf, cs->last_cont_ptid,
+				      &cs->last_cont_status);
+		putpkt (cs->own_buf);
+	      }
+	    else
+	      putpkt (waitee_cs->own_buf);
+	  }
+	break;
+      }
+    case vConts:
+      {
+	if (non_stop)
+	  {
+	    debug_printf ("vConts non stop exit\n");
+	    if (cs->last_status.kind != TARGET_WAITKIND_EXITED)
+	      cs->nonstop_pending = pending_notifier;
+	  }
+	else if (cs->last_status.kind != TARGET_WAITKIND_EXITED)
+	  {
+	    debug_printf ("vConts all stop not exit %s %s\n", 
waitee_cs->own_buf, strstr (waitee_cs->own_buf, "T05syscall"));
+	    putpkt (waitee_cs->own_buf);
+	  }
+	else if (cs->last_status.kind == TARGET_WAITKIND_EXITED)
+	  {
+	    debug_printf ("vConts all stop exit\n");
+	    putpkt (waitee_cs->own_buf);
+	  }
+	break;
+      }
+    case vContt:
+      {
+	if (!waitee_cs ||
+	    (waitee_cs->last_status.kind != TARGET_WAITKIND_EXITED
+		&& waitee_cs && waitee_cs->last_status.kind != TARGET_WAITKIND_STOPPED))
+	  {
+	    char *notif_buf, *out_buf;
+	    notif_buf = (char*) alloca (PBUFSIZ + 1);
+	    write_ok (notif_buf);
+	    putpkt (notif_buf);
+
+	    for_each_thread (queue_stop_reply_callback);
+	    notif_write_event (&notif_stop, notif_buf);
+	    out_buf = (char*) alloca (strlen (notif_buf) + 8);
+	    xsnprintf (out_buf, PBUFSIZ, "%s:", notif_stop.notif_name);
+	    strcat (out_buf, notif_buf);
+	    if (debug_threads)
+	      debug_printf ("%s:%d Notifying fd=%d\n", __FUNCTION__, __LINE__,
+			    cs->file_desc);
+	    putpkt_notif (out_buf);
+	    if (debug_threads)
+	      debug_printf ("%s:%d %s\n", __FUNCTION__, __LINE__, out_buf);
+	  }
+	break;
+      }
+    case vRun:
+      {
+	strcpy (cs->own_buf, "OK");
+	putpkt (cs->own_buf);
+	break;
+      }
+    default:
+      break;
+    };
+
+  client_states.set_client_state (save_client_state->file_desc);
+}
+
+
+/* What is the wait status of the clients sharing CURRENT_CS's server 
state? */
+
+static void
+analyze_group (client_state & current_cs, int *have_waitee)
+{
+  client_state *csi;
+
+  *have_waitee = 0;
+  std::map<gdb_fildes_t,client_state*>::iterator it;
+
+  for (it = client_states.cs.begin(); it != client_states.cs.end(); ++it)
+    {
+      csi = it->second;
+      if (attached_to_same_proc (&current_cs, csi))
+	{
+	  if (csi->pending == pending_waitee || csi->pending == none_pending)
+	    *have_waitee += 1;
+	}
+    }
+}
+
+
+/* Determine the state of client CS with respect to other clients sharing
+   the same server process */
+
+static int
+setup_multiplexing (client_state & current_cs)
+{
+  /***
+      If we have two independent clients 4 and 7 and 4 is the current
+      client with a vConts packet then we change both client's state
+      BEFORE
+      packet_type last_packet_type pending last_status_.kind
+      4 vConts    vConts	   not-waiting stopped
+      7 other     vAttach	   not-waiting stopped
+      AFTER
+      4 vConts    vConts	   step-waiter stopped
+      7 other     vAttach	   waitee      stopped
+
+      If we have two dependent clients 4 and 7 and 4 is the current 
client with a
+      vContc packet then we change nothing here.  process_serial_event 
will handle
+      the vContc then do_multiplexing will decide to either continue 
with client 4
+      or wakeup and continue with client 7.
+      4 vContc vConts waitee stopped
+      7 vContc vContc waiter stopped
+  ***/
+
+  client_state *same_pid_cs = NULL;
+
+  if (!have_multiple_clients(current_cs.file_desc))
+    return 1;
+
+  dump_client_state (__FUNCTION__, "");
+
+  if (current_cs.packet_type == vContc || current_cs.packet_type == vConts)
+    current_cs.nonstop_pending = none_pending;
+
+  std::map<gdb_fildes_t,client_state*>::iterator it;
+
+  for (it = client_states.cs.begin(); it != client_states.cs.end(); ++it)
+    {
+      same_pid_cs = it->second;
+      if (! attached_to_same_proc (&current_cs, same_pid_cs))
+	continue;
+
+      switch (same_pid_cs->pending)
+	{
+	case /* same_pid_cs->pending */ none_pending:
+	  /* found a client that has nothing pending */
+	  /* The current_cs vContc will wait; found same_pid_cs will proceed */
+	  switch (current_cs.packet_type)
+	    {
+	    case /* current_cs.packet_type */ vContc:
+		/* Don't make a syscall client a waitee as a waiter cannot
+		   depend on receiving a reply from it */
+	      if (current_cs.last_packet_type != vRun
+		  && ! same_pid_cs->catch_syscalls)
+		{
+		  current_cs.pending = pending_cont_waiter;
+		  same_pid_cs->pending = pending_waitee;
+		}
+	      break;
+	    }
+	  break;
+	case /* same_pid_cs->pending */ pending_cont_waiter:
+	  switch (current_cs.packet_type)
+	    {
+	      /* Current client is continuing and found another waiter client */
+	    case /* current_cs.packet_type */ vContc:
+	      {
+		int have_waitee;
+		analyze_group (current_cs, &have_waitee);
+		dump_client_state (__FUNCTION__, "waitee/waiter switch");
+		/* Don't want to deadlock on everyone waiting */
+		if (current_cs.pending == pending_waitee && have_waitee)
+		  current_cs.pending = pending_cont_waiter;
+	      }
+	      break;
+	    }
+	  break;
+	case /* same_pid_cs->pending */ pending_waitee:
+	  switch (current_cs.packet_type)
+	    {
+	      /* Current client is continuing and found another waitee client */
+	    case /* current_cs.packet_type */ vContc:
+	      {
+		/* Don't make a syscall client a waitee as a waiter cannot
+		   depend on receiving a reply from it */
+		if (!(non_stop
+		      && current_cs.catch_syscalls
+		      && it->second->packet_type == vContc))
+		  current_cs.pending = pending_cont_waiter;
+	      }
+	      break;
+	    }
+	  debug_printf ("%s DBG %s catching=%d\n", __FUNCTION__,
+			target_waitstatus_to_string (&get_client_state().last_status).c_str(),
+			current_cs.catch_syscalls);
+	} /* switch same_pid_cs->pending */
+    } /* for same_pid_cs */
+
+
+  switch (current_cs.pending)
+    {
+    case pending_cont_waiter:
+      switch (current_cs.last_packet_type)
+        {
+	case vRun:
+	  break;
+	default:
+	  /* Current client is continuing and waiting so don't reply to this
+	     packet now; it will be replied to later in do_multiplexing */
+	  if (current_cs.packet_type == vContc)
+	    {
+	      debug_printf ("%s DBG %s %d\n", __FUNCTION__,
+			target_waitstatus_to_string (&get_client_state().last_status).c_str(),
+			current_cs.catch_syscalls);
+	      dump_client_state (__FUNCTION__, "* waiting");
+	      current_cs.last_cont_ptid = current_cs.general_thread;
+	      current_cs.last_cont_status = current_cs.last_status;
+	      return 0;		/* Reply to packet later */
+	    }
+	} /* switch current_cs.last_packet_type */
+      __attribute__ ((fallthrough));
+    default:
+      if (current_cs.catch_syscalls && current_cs.packet_type == vContc
+	  && current_cs.displaced_step == in_displaced_step)
+	{
+	  dump_client_state (__FUNCTION__, "* waiting");
+	  return 0;
+	}
+      dump_client_state (__FUNCTION__, "* continuing");
+      return 1;			/* Reply to packet now */
+    } /* switch current_cs.pending */
+}
+
+
+/* Send a notification to a pending client.  Called via the
+   handle_target_event notification mechanism.  This is a non-stop
+   variation of do_multiplexing */
+
+int
+notify_clients (char *buffer, int have_first_notify)
+{
+  int save_client_fd = client_states.current_cs->file_desc;
+  client_state *save_client_cs = client_states.current_cs;
+  char *okay_buf = (char*) alloca (4);
+  int have_syscall = 0;
+
+  dump_client_state (__FUNCTION__, "");
+
+  write_ok (okay_buf);
+
+  std::map<gdb_fildes_t,client_state*>::iterator it;
+  for (it = client_states.cs.begin(); it != client_states.cs.end(); ++it)
+    {
+      /* Is this a client attached to the same process? */
+      if (! attached_to_same_proc (client_states.current_cs, it->second))
+	continue;
+
+      switch (save_client_cs->last_status.kind)
+      {
+	case TARGET_WAITKIND_SYSCALL_ENTRY:
+	case TARGET_WAITKIND_SYSCALL_RETURN:
+	  have_syscall = 1;
+	  break;
+	case TARGET_WAITKIND_EXITED:
+	  client_states.set_client_state (it->second->file_desc);
+	  putpkt (okay_buf);
+	  putpkt_notif (buffer);
+	  client_states.set_client_state (save_client_fd);
+	  return 1;
+        case TARGET_WAITKIND_STOPPED:
+	  /* Have more than 1 notify so also send to shadow client */
+	  if (save_client_cs->packet_type == vStopped)
+		it->second->nonstop_pending = pending_notifier;
+	  __attribute__ ((fallthrough));
+	default:
+	  /* Only syscall clients need to see a syscall packet */
+	  if (save_client_cs->catch_syscalls)
+	    {
+	      client_states.set_client_state (it->second->file_desc);
+	      return 1;
+	    }
+      }
+
+      /* syscall continue was erroneously caught by by a non syscall 
client */
+      if (save_client_cs->packet_type == other_packet
+	  && it->second->catch_syscalls)
+	return 0;
+
+      /* client wants the notification */
+      if (it->second->nonstop_pending == pending_notifier)
+	{
+	  /* Also send the notification to the attached client */
+	  client_states.set_client_state (it->second->file_desc);
+	  if (debug_threads)
+	    debug_printf ("%s:%d Notifying fd=%d\n", __FUNCTION__, __LINE__, 
it->second->file_desc);
+	  /* This is the first notification */
+	  if (have_first_notify
+	      && (/*is_waiter (it->second)
+		  ||*/ (save_client_cs->packet_type != vStopped
+		      && it->second->nonstop_pending == pending_notifier)))
+	    {
+	      putpkt (okay_buf);
+	      putpkt_notif (buffer);
+	    }
+	  else			/* This is another notification in the group */
+	    {
+	      if (it->second->packet_type == vStopped)
+		putpkt (buffer);
+	    }
+	  client_states.set_client_state (save_client_fd);
+	  it->second->pending = none_pending;
+	  it->second->nonstop_pending = pending_notified;
+	}
+    }
+  if (have_syscall && !save_client_cs->catch_syscalls)
+    return 0;
+  else
+    return 1;
+}
+
+
+/* Resolve the state of client WAITEE_CS with respect to other clients
+   sharing the same server process */
+
+static int
+do_multiplexing (client_state & current_cs)
+{
+  /***
+  If we have two dependent clients 4 and 7 and 4 is the current client 
with a
+  vContc packet then if the handling of vContc resulted in hitting a 
client 7
+  breakpoint then we wakeup client 7.
+
+  BEFORE
+  packet_type last_packet_type pending last_status_.kind
+  4 vContc    vConts		waitee stopped
+  7 vContc    vContc		waiter stopped
+  AFTER
+  4 vContc    vConts		waiter stopped
+  7 vContc    vContc		waitee stopped
+
+  Otherwise we continue with client 4.
+  4 vContc    vConts		waitee stopped
+  7 vContc    vContc		waiter stopped
+  ***/
+
+  client_state *same_pid_cs = NULL;
+  int make_waitee_a_waiter = 0;
+
+  if (!have_multiple_clients(current_cs.file_desc))
+    return 1;
+
+  switch (current_cs.packet_type)
+    {
+    case other_packet:
+      break;
+    case vContt:
+      if (current_cs.last_packet_type == vAttach ||
+	  current_cs.last_packet_type == Hg)
+	{
+	  resolve_waiter (&current_cs, NULL);
+	  dump_client_state (__FUNCTION__, "resolved vContt");
+	  current_cs.last_packet_type = other_packet;
+	  return 0;
+	}
+      __attribute__ ((fallthrough));
+    default:
+          current_cs.last_packet_type = current_cs.packet_type;
+    }
+
+  dump_client_state (__FUNCTION__, "");
+
+  /* We are only interested in a current nonwaiting client that is 
continuing */
+  switch (current_cs.packet_type)
+    {
+    case vContc:
+    case vContt:
+    case vConts:
+    case Detach:
+      if (current_cs.pending == pending_waitee)
+	break;
+      __attribute__ ((fallthrough));
+    default:
+      dump_client_state (__FUNCTION__, "no action taken");
+      return 1;
+    }
+
+  std::map<gdb_fildes_t,client_state*>::iterator it;
+
+  for (it = client_states.cs.begin(); it != client_states.cs.end(); ++it)
+    {
+      same_pid_cs = it->second;
+      client_state *waiter_cs = NULL;
+      int want_waiter_resolved = 0;
+
+      /* Is this a waiting continuing client attached to the cs process */
+      if (! attached_to_same_proc (&current_cs, same_pid_cs)
+	  || (same_pid_cs->pending != pending_cont_waiter)
+	  || (same_pid_cs->packet_type != vContc))
+	continue;
+
+      switch (current_cs.packet_type)
+	{
+	case vConts:
+	  current_cs.last_cont_ptid = current_cs.general_thread;
+	  current_cs.last_cont_status = current_cs.last_status;
+	} /* switch current_cs.packet_type */
+
+      switch (get_client_state().last_status.kind)
+	{
+	case TARGET_WAITKIND_EXITED:
+	  waiter_cs = client_states.set_client_state (same_pid_cs->file_desc);
+	  make_waitee_a_waiter = 1;
+	  want_waiter_resolved = 1;
+	  break;
+	case TARGET_WAITKIND_SYSCALL_ENTRY:
+	case TARGET_WAITKIND_SYSCALL_RETURN:
+	  /* current client continued and got a syscall
+	     which another client was waiting for */
+	  if (same_pid_cs->catch_syscalls
+	      || (current_cs.catch_syscalls && current_cs.packet_type == Detach))
+	    {
+	      waiter_cs = client_states.set_client_state (same_pid_cs->file_desc);
+	      make_waitee_a_waiter = 1;
+	      want_waiter_resolved = 1;
+	    }
+	  break;
+        case TARGET_WAITKIND_STOPPED:
+	  /* we want only syscalls but got something else */
+	  if (current_cs.catch_syscalls)
+	    {
+	      waiter_cs = client_states.set_client_state (same_pid_cs->file_desc);
+	      make_waitee_a_waiter = 1;
+	      want_waiter_resolved = 1;
+	    }
+	  else if (get_first_thread () != NULL)
+	    {
+	      struct regcache *regcache;
+	      CORE_ADDR point_addr = 0;
+
+	      if ((*the_target->stopped_by_watchpoint)())
+		point_addr = (*the_target->stopped_data_address) ();
+	      else
+		{
+		  regcache = current_thread->regcache_data;
+		  point_addr = (*the_target->read_pc) (regcache);
+		}
+	      if (point_addr)
+		{
+		  waiter_cs = client_states.set_client_state (same_pid_cs->file_desc);
+		  /* Does found client have a breakpoint at PC? */
+		  want_waiter_resolved = gdb_breakpoint_here (point_addr);
+		}
+	      else if (current_cs.packet_type == vConts
+		       && current_cs.last_status.kind == TARGET_WAITKIND_STOPPED)
+		{
+		  /* there is no target->stopped_by_single_step so just assume that */
+		  waiter_cs = client_states.set_client_state (same_pid_cs->file_desc);
+		  want_waiter_resolved = 1;
+		}
+	    }
+	  break;
+	default:
+	  /* we want only syscalls but got something else */
+	  if (current_cs.catch_syscalls)
+	    {
+	      waiter_cs = client_states.set_client_state (same_pid_cs->file_desc);
+	      make_waitee_a_waiter = 1;
+	      want_waiter_resolved = 1;
+	    }
+	} /* switch last_status->kind */
+
+      if (want_waiter_resolved)
+	{
+	  /* We reached the other client's breakpoint, belatedly reply */
+	  waiter_cs->copy_status (current_cs);
+	  resolve_waiter (waiter_cs, &current_cs);
+	  current_cs.pending = none_pending;
+	  waiter_cs->pending = pending_waitee;
+	}
+      client_state *lcs = client_states.set_client_state 
(current_cs.file_desc);
+      current_cs = *lcs;
+    } /* for (same_pid_cs  */
+
+  if (make_waitee_a_waiter && current_cs.packet_type == vContc)
+    {
+      /* Switch the current and waiting clients.  The packet will be 
replied
+	 to in a later do_multiplexing call */
+      current_cs.pending = pending_cont_waiter;
+      dump_client_state (__FUNCTION__, "* waiting");
+      current_cs.last_cont_ptid = current_cs.general_thread;
+      current_cs.last_cont_status = current_cs.last_status;
+      return 0;
+    }
+  else
+    {
+      dump_client_state (__FUNCTION__, "* continuing");
+      return 1;
+    }
+}
+
+
+/**********************************/
+
  /* Put a stop reply to the stop reply queue.  */

  static void
@@ -210,14 +1136,6 @@ discard_queued_stop_replies (ptid_t ptid)
  		 remove_all_on_match_ptid, &ptid);
  }

-static void
-vstop_notif_reply (struct notif_event *event, char *own_buf)
-{
-  struct vstop_notif *vstop = (struct vstop_notif *) event;
-
-  prepare_resume_reply (own_buf, vstop->ptid, &vstop->status);
-}
-
  /* QUEUE_iterate callback helper for in_queued_stop_replies.  */

  static int
@@ -250,11 +1168,6 @@ in_queued_stop_replies (ptid_t ptid)
  			 in_queued_stop_replies_ptid, &ptid);
  }

-struct notif_server notif_stop =
-{
-  "vStopped", "Stop", NULL, vstop_notif_reply,
-};
-
  static int
  target_running (void)
  {
@@ -324,8 +1237,6 @@ attach_inferior (int pid)
    return 0;
  }

-extern int remote_debug;
-
  /* Decode a qXfer read request.  Return 0 if everything looks OK,
     or -1 otherwise.  */

@@ -645,6 +1556,7 @@ handle_general_set (char *own_buf)
  	    }
  	  else
  	    process->syscalls_to_catch.push_back (ANY_SYSCALL);
+	  client_states.current_cs->catch_syscalls = 1;
  	}

        write_ok (own_buf);
@@ -745,6 +1657,13 @@ handle_general_set (char *own_buf)
  	  return;
  	}

+      if (client_states.cs.size() > 2 && (non_stop ^ req))
+	{
+	  write_enn (own_buf);
+	  return;
+	}
+
+
        req_str = req ? "non-stop" : "all-stop";
        if (start_non_stop (req) != 0)
  	{
@@ -960,6 +1879,8 @@ monitor_show_help (void)
    monitor_output ("    Options: all, none");
    monitor_output (", timestamp");
    monitor_output ("\n");
+  monitor_output ("  client status\n");
+  monitor_output ("    Display status of multiple clients\n");
    monitor_output ("  exit\n");
    monitor_output ("    Quit GDBserver\n");
  }
@@ -1198,6 +2119,13 @@ handle_detach (char *own_buf)

    process_info *process;

+  if (have_multiple_clients(cs.file_desc) && cs.catch_syscalls)
+    {
+      write_ok (cs.own_buf);
+      putpkt (cs.own_buf);
+      cs = client_states.delete_client_state(cs.file_desc);
+      return;
+    }
    if (cs.multi_process)
      {
        /* skip 'D;' */
@@ -1398,6 +2326,43 @@ handle_monitor_command (char *mon, char *own_buf)
  	  write_enn (own_buf);
  	}
      }
+  else if (strcmp (mon, "client status") == 0)
+    {
+      client_state *csidx;
+      char *result = (char*)"";
+      char *old_result = NULL;
+      std::map<gdb_fildes_t,client_state*>::iterator it;
+
+      for (it = client_states.cs.begin(); it != client_states.cs.end(); 
++it)
+	{
+	  csidx = it->second;
+	  if (csidx->file_desc > 0)
+	    {
+	      int asr;
+	      old_result = result;
+	      asr = asprintf (&result, "%s fd %d %s %s is %s", result,
+			csidx->file_desc, target_pid_to_str (csidx->general_thread),
+			csidx->last_status.kind != TARGET_WAITKIND_IGNORE ? 
waitkind_str[csidx->last_status.kind] : "",
+			pending_types_str[csidx->pending]);
+	      if (strlen (old_result))
+		free (old_result);
+	      if (asr)
+		old_result = result;
+	      if (csidx->packet_type)
+		asr = asprintf (&result, "%s with a current %s request\n", result,
+			  packet_types_str[csidx->packet_type]);
+	      else
+		asr = asprintf (&result, "%s\n", result);
+	      if (strlen (old_result))
+		free (old_result);
+	    }
+	}
+      if (strlen (result) > 0)
+	{
+	  monitor_output (result);
+	  free (result);
+	}
+    }
    else if (strcmp (mon, "help") == 0)
      monitor_show_help ();
    else if (strcmp (mon, "exit") == 0)
@@ -1653,6 +2618,7 @@ handle_qxfer_statictrace (const char *annex,
  static void
  handle_qxfer_threads_worker (thread_info *thread, struct buffer *buffer)
  {
+  client_state &cs = get_client_state ();
    ptid_t ptid = ptid_of (thread);
    char ptid_s[100];
    int core = target_core_of_thread (ptid);
@@ -1662,6 +2628,11 @@ handle_qxfer_threads_worker (thread_info *thread, 
struct buffer *buffer)
    gdb_byte *handle;
    bool handle_status = target_thread_handle (ptid, &handle, &handle_len);

+  /* TODO an attached client does not know about multiple inferiors */
+  if (ptid.pid() != cs.general_thread.pid()
+      && have_multiple_clients (cs.file_desc))
+    return;
+
    write_ptid (ptid_s, ptid);

    buffer_xml_printf (buffer, "<thread id=\"%s\"", ptid_s);
@@ -2635,7 +3606,7 @@ handle_query (char *own_buf, int packet_len, int 
*new_packet_len_p)
  	  return;
  	}

-      strcpy (own_buf, process->attached ? "1" : "0");
+      strcpy (own_buf, process->attached || have_multiple_clients 
(cs.file_desc) ? "1" : "0");
        return;
      }

@@ -2910,9 +3881,27 @@ handle_v_attach (char *own_buf)
  {
    client_state &cs = get_client_state ();
    int pid;
+  int status;

    pid = strtol (own_buf + 8, NULL, 16);
-  if (pid != 0 && attach_inferior (pid) == 0)
+  status = add_client_by_pid(pid);
+  if (status < 0)
+    {
+      sprintf (own_buf, "E.Attached client non-stop/all-stop mode does 
not match the running client.");
+      return 0;
+    }
+  else if (status == 1)
+    {
+      if (! non_stop)
+	{
+	  strcpy (own_buf, "?");
+	  prepare_resume_reply (own_buf, cs.general_thread, &cs.last_status);
+	}
+      else
+	write_ok (own_buf);
+      return 1;
+    }
+  else if (pid != 0 && attach_inferior (pid) == 0)
      {
        /* Don't report shared library events after attaching, even if
  	 some libraries are preloaded.  GDB will always poll the
@@ -3336,8 +4325,8 @@ handle_status (char *own_buf)
      {
        for_each_thread (queue_stop_reply_callback);

-      /* The first is sent immediatly.  OK is sent if there is no
-	 stopped thread, which is the same handling of the vStopped
+      /* The first is sent immediately.  OK is sent if there is no
+	 stopped thread, which is the same handling as the vStopped
  	 packet (by design).  */
        notif_write_event (&notif_stop, cs.own_buf);
      }
@@ -3572,6 +4561,9 @@ captured_main (int argc, char *argv[])
    volatile int multi_mode = 0;
    volatile int attach = 0;
    int was_running;
+
+  int remote_desc = get_remote_desc();
+  client_states.set_client_state (remote_desc);
    bool selftest = false;
  #if GDB_SELF_TEST
    const char *selftest_filter = NULL;
@@ -4036,16 +5028,33 @@ process_serial_event (void)
    disable_async_io ();

    response_needed = 0;
-  packet_len = getpkt (cs.own_buf);
+  packet_len = getpkt (cs.file_desc, cs.own_buf);
    if (packet_len <= 0)
      {
+      gdb_fildes_t fdt;
        remote_close ();
+      fdt = get_first_client_fd ();
        /* Force an event loop break.  */
-      return -1;
+      if (fdt > 0)
+	{
+	  client_state * lcs = client_states.set_client_state (fdt);
+	  cs = *lcs;
+	  set_remote_desc (fdt);
+	  packet_len = getpkt (cs.file_desc, cs.own_buf);
+	}
+      else
+	return -1;
      }
+
    response_needed = 1;

    char ch = cs.own_buf[0];
+
+  cs.packet_type = get_packet_type (cs);
+
+  if (! setup_multiplexing (cs))
+    return 0;
+
    switch (ch)
      {
      case 'q':
@@ -4368,6 +5377,9 @@ process_serial_event (void)
        break;
      }

+  if (! do_multiplexing (get_client_state()))
+    return 0;
+
    if (new_packet_len != -1)
      putpkt_binary (cs.own_buf, new_packet_len);
    else
@@ -4391,6 +5403,7 @@ handle_serial_event (int err, gdb_client_data 
client_data)

    /* Really handle it.  */
    if (process_serial_event () < 0)
+
      return -1;

    /* Be sure to not change the selected thread behind GDB's back.
@@ -4400,6 +5413,29 @@ handle_serial_event (int err, gdb_client_data 
client_data)
    return 0;
  }

+/* Dump stop notifications */
+
+static void
+dump_stop_queue (const char *function, const char *comment)
+{
+  struct queue_elem_notif_event_p *queue_elem;
+  struct vstop_notif *vstop_notif;
+
+  if (!debug_threads)
+    return;
+  if (notif_stop.queue->head == 0)
+    return;
+  debug_printf ("** stop queue at %s: %s\n", function, comment);
+  for (queue_elem = notif_stop.queue->head;
+       queue_elem != 0;
+       queue_elem = queue_elem->next)
+    {
+      vstop_notif = (struct vstop_notif*)queue_elem->data;
+      debug_printf ("%d %s\n", vstop_notif->ptid.pid(), 
target_waitstatus_to_string (&vstop_notif->status).c_str());
+    }
+}
+
+
  /* Push a stop notification on the notification queue.  */

  static void
@@ -4418,13 +5454,20 @@ push_stop_notification (ptid_t ptid, struct 
target_waitstatus *status)
  int
  handle_target_event (int err, gdb_client_data client_data)
  {
+  client_state *csi, *save_csi;
    client_state &cs = get_client_state ();
+
    if (debug_threads)
      debug_printf ("handling possible target event\n");

    cs.last_ptid = mywait (minus_one_ptid, &cs.last_status,
  		      TARGET_WNOHANG, 1);

+  if (debug_threads)
+    debug_printf ("%s fd=%d queue=%d %s\n", __FUNCTION__, 
client_states.current_cs->file_desc, notif_stop.queue->head == NULL ? 0 : 1,
+		  waitkind_str[cs.last_status.kind]);
+  save_csi = client_states.current_cs;
+
    if (cs.last_status.kind == TARGET_WAITKIND_NO_RESUMED)
      {
        if (gdb_connected () && report_no_resumed)
@@ -4436,6 +5479,25 @@ handle_target_event (int err, gdb_client_data 
client_data)
        struct process_info *process = find_process_pid (pid);
        int forward_event = !gdb_connected () || process->gdb_detached;

+      if ((cs.last_status.kind == TARGET_WAITKIND_SYSCALL_ENTRY
+	  || cs.last_status.kind == TARGET_WAITKIND_SYSCALL_RETURN)
+	  && have_multiple_clients (cs.file_desc))
+	{
+	  std::map<gdb_fildes_t,client_state*>::iterator it;
+
+	  for (it = client_states.cs.begin(); it != client_states.cs.end(); ++it)
+	    {
+	      csi = it->second;
+	      if (attached_to_same_proc (save_csi, csi)
+		  && csi->catch_syscalls)
+		{
+		  save_csi = client_states.current_cs;
+		  csi->nonstop_pending = pending_notifier;
+		  break;
+		}
+	    }
+	}
+
        if (cs.last_status.kind == TARGET_WAITKIND_EXITED
  	  || cs.last_status.kind == TARGET_WAITKIND_SIGNALLED)
  	{
@@ -4492,6 +5554,7 @@ handle_target_event (int err, gdb_client_data 
client_data)
    /* Be sure to not change the selected thread behind GDB's back.
       Important in the non-stop mode asynchronous protocol.  */
    set_desired_thread ();
+  client_states.set_client_state (save_csi->file_desc);

    return 0;
  }
diff --git a/server.h b/server.h
index 5e41e2f595d..f423406aa22 100644
--- a/server.h
+++ b/server.h
@@ -61,6 +61,8 @@ int vsnprintf(char *str, size_t size, const char 
*format, va_list ap);
  #include "target.h"
  #include "mem-break.h"
  #include "environ.h"
+#include <list>
+#include <map>

  /* Target-specific functions */

@@ -92,6 +94,7 @@ extern void handle_v_requests (char *own_buf, int 
packet_len,
  			       int *new_packet_len);
  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 int notify_clients (char *buffer, int first);

  /* Get rid of the currently pending stop replies that match PTID.  */
  extern void discard_queued_stop_replies (ptid_t ptid);
@@ -121,6 +124,9 @@ extern int in_queued_stop_replies (ptid_t ptid);
  /* Definition for any syscall, used for unfiltered syscall reporting.  */
  #define ANY_SYSCALL (-2)

+/* Trace child processes created via fork or clone.  */
+#define NO_SYSCALL (-3)
+
  /* After fork_inferior has been called, we need to adjust a few
     signals and call startup_inferior to start the inferior and consume
     its first events.  This is done here.  PID is the pid of the new
@@ -133,6 +139,17 @@ extern gdb_environ *get_environ ();
  extern unsigned long signal_pid;


+enum displaced_step_type
+  { not_displaced_step, in_displaced_step, maybe_displaced_step };
+typedef enum displaced_step_type displaced_step_type;
+
+/* The packet type of a client packet */
+
+enum packet_types
+  { other_packet, vContc, vConts, vContr, vContt, vRun, vAttach, Hg, 
g_or_m, Detach, vStopped };
+typedef enum packet_types packet_types;
+
+
  /* Description of the client remote protocol state for the currently
     connected client.  */

@@ -141,6 +158,19 @@ struct client_state
    client_state ():
      own_buf ((char *) xmalloc (PBUFSIZ + 1))
    {}
+  client_state (gdb_fildes_t fd, client_state *csidx);
+
+  gdb_fildes_t file_desc;
+  int packet_type = other_packet;
+  int last_packet_type = other_packet;
+  displaced_step_type displaced_step = not_displaced_step; // +
+  int pending = 0;
+  int nonstop_pending = 0;
+  int catch_syscalls = 0;
+  int syscall_op = NO_SYSCALL;
+  ptid_t last_cont_ptid;
+  ptid_t new_general_thread;
+  struct target_waitstatus last_cont_status;

    /* The thread set with an `Hc' packet.  `Hc' is deprecated in favor of
       `vCont'.  Note the multi-process extensions made `vCont' a
@@ -148,10 +178,10 @@ struct client_state
       CONT_THREAD can be null_ptid for no `Hc' thread, minus_one_ptid for
       resuming all threads of the process (again, `Hc' isn't used for
       multi-process), or a specific thread ptid_t.  */
-  ptid_t cont_thread;
+  ptid_t cont_thread = null_ptid; // +

    /* The thread set with an `Hg' packet.  */
-  ptid_t general_thread;
+  ptid_t general_thread = null_ptid; // +

    int multi_process = 0;
    int report_fork_events = 0;
@@ -183,8 +213,8 @@ struct client_state
    int program_signals_p = 0;

    /* Last status reported to GDB.  */
-  struct target_waitstatus last_status;
-  ptid_t last_ptid;
+  struct target_waitstatus last_status; // +
+  ptid_t last_ptid; // +

    char *own_buf;

@@ -198,9 +228,27 @@ struct client_state

    int current_traceframe = -1;

+  void copy_status (client_state &csidx);
+};
+
+
+struct multi_client_states
+{
+public:
+  std::map<gdb_fildes_t,client_state*> cs;
+  client_state *current_cs;
+
+  client_state & get_client_state (void) { return *current_cs; }
+  void set_current_client (client_state *cs) { current_cs = cs; }
+
+  client_state * set_client_state (gdb_fildes_t);
+  void free_client_state (client_state *cs);
+  client_state & delete_client_state (gdb_fildes_t fd);
  };

-client_state &get_client_state ();
+client_state & get_client_state ();
+struct multi_client_states & get_client_states (void);
+bool have_multiple_clients (gdb_fildes_t fd);

  #include "gdbthread.h"
  #include "inferiors.h"
diff --git a/multi-client.exp b/multi-client.exp
new file mode 100644
index 00000000000..9b06b012824
--- /dev/null
+++ b/multi-client.exp
@@ -0,0 +1,440 @@
+# Copyright (C) 2018 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+exp_internal 0
+
+load_lib gdbserver-support.exp
+load_lib prelink-support.exp
+
+if {[skip_gdbserver_tests]} {
+    return 0
+}
+
+set test "multi-client"
+global srcdir
+global subdir
+global gdbserver_gdbport
+global gdbserver_reconnect_p
+global server_spawn_id
+global target_pid
+global pgrep_spawn_id
+# set testpath [standard_output_file $testfile]
+
+verbose "srcdir=$srcdir subdir=$subdir [standard_output_file $test]"
+set testfile catch-syscall
+set srcfile ../gdb.base/catch-syscall.c
+set testpath [standard_output_file $testfile]
+set gdbserver_reconnect_p 1
+
+set testfile2 strace-threads
+set srcfile2 strace-threads.c
+set testpath2 [standard_output_file $testfile2]
+
+if { [prepare_for_testing $test $testfile $srcfile debug] } {
+    return -1
+}
+if {[build_executable $test $testfile $srcfile debug] == -1} {
+    return -1
+}
+
+if {[build_executable $test $testfile2 $srcfile2 {debug 
additional_flags=-lpthread}] == -1} {
+    return -1
+}
+
+set use_gdb_stub 0
+set strace_spawn_id ""
+
+proc start_client { TESTPATH NONSTOP COMMENT } {
+    global test
+    global GDB
+    global MULTI_GDBFLAGS
+    global gdbserver_gdbport
+    global gdb_spawn_id
+    global inferior_spawn_id
+    global srcdir
+    global subdir
+    gdb_exit
+    gdb_start
+    gdb_load $TESTPATH
+    gdb_reinitialize_dir $srcdir/$subdir
+    gdb_test_no_output "set remotetimeout 600"
+    gdb_test_no_output "set non-stop $NONSTOP"
+    gdb_test "target extended-remote $gdbserver_gdbport"
+    gdb_test_no_output "set remote exec-file $TESTPATH" "set remote 
exec-file"
+    return $gdb_spawn_id
+}
+
+proc start_strace { ATTACH_FLAGS } {
+    global test
+    set STRACE [auto_execok strace]
+    verbose "strace is $STRACE $ATTACH_FLAGS"
+    set res [remote_spawn host "$STRACE $ATTACH_FLAGS"]
+    expect_before {
+        -i $res " invalid option "  {
+            xfail "no gdb remote protocol strace"
+            return 0
+        }
+        eof exit
+    }
+    sleep 5
+    if { $res < 0 || $res == "" } {
+        perror "$test Spawning $STRACE failed."
+        return 1
+    }
+    return $res
+}
+
+proc get_target_pid { target_exec } {
+    global test
+    global target_pid
+    global pgrep_spawn_id
+
+    set target_pid -1
+    set res [remote_spawn host "pgrep $target_exec"]
+    sleep 1
+    expect {
+	-i $res -re {[0-9][0-9]*} { set target_pid $expect_out(buffer) }
+    }
+    if { $target_pid < 0 } {
+	perror "$test Failed to get pid of target process. $expect_out(buffer)"
+	return 1
+    }
+    close -i $res
+    set pgrep_spawn_id $res
+    return $target_pid
+}
+
+proc gdb_command { COMMAND RESPONSE COMMENT } {
+    global gdb_spawn_id
+    global gdb_prompt
+    global test
+    set ok 0
+    send -i $gdb_spawn_id "$COMMAND\n"
+    if { [string length $RESPONSE] > 0 } {
+	gdb_test_multiple "" "$COMMENT" {
+	    -i $gdb_spawn_id -re "$RESPONSE.*\r\n$gdb_prompt $" {
+		incr ok;
+	    }
+	}
+	if {$ok == 1} {
+	    pass "$COMMENT"
+	}
+    }
+}
+
+set clean_idx 0
+
+proc cleanup_server_and_clients { } {
+    global strace_spawn_id
+    global server_spawn_id
+    global target_pid
+    global gdb_spawn_id
+    global inferior_spawn_id
+    global pgrep_spawn_id
+    global clean_idx
+
+    incr clean_idx
+    close_gdbserver
+    catch {exec kill -KILL [exp_pid -i $strace_spawn_id]}
+    catch {exec kill -KILL [exp_pid -i $server_spawn_id]}
+    catch {exec kill -KILL [exp_pid -i $gdb_spawn_id]}
+    catch {exec kill -KILL [exp_pid -i $inferior_spawn_id]}
+    catch {exec kill -KILL [exp_pid -i $pgrep_spawn_id]}
+    if { $target_pid > 1 } {catch {exec kill -KILL $target_pid}}
+    gdb_exit
+}
+
+foreach NONSTOP { off on } {
+
+#-------------------------------------------------------
+
+verbose "##### Test coordination of a gdb client and an strace client"
+
+set res [gdbserver_start "--multi" ""]
+sleep 2
+set gdbserver_protocol [lindex $res 0]
+set gdbserver_gdbport [lindex $res 1]
+
+start_client $testpath "$NONSTOP" "non-stop $NONSTOP"
+
+gdb_command "b main" "Breakpoint 1 at" "gdb/strace/0-thr/$NONSTOP b main"
+
+gdb_command "b 76" "Breakpoint 2 at" "gdb/strace/0-thr/$NONSTOP b _exit"
+
+gdb_command "run" "Breakpoint 1," "gdb/strace/0-thr/$NONSTOP hit b main"
+
+set target_pid [get_target_pid catch-syscall]
+
+set strace_spawn_id [start_strace "-f -G $gdbserver_gdbport -o 
[standard_output_file strace-$NONSTOP.out] -p $target_pid"]
+if { $strace_spawn_id == 0 || $strace_spawn_id == ""} {
+    return 0
+}
+
+#		close (-1);
+gdb_command "next" "" ""
+gdb_command "next" "close" "gdb/strace/0-thr/$NONSTOP next close"
+
+#		chroot (".");
+gdb_command "next" "chroot" "gdb/strace/0-thr/$NONSTOP next chroot"
+
+#		pipe (fd);
+gdb_command "next" "pipe" "gdb/strace/0-thr/$NONSTOP next pipe"
+
+#		write (fd[1], buf1, sizeof (buf1));
+gdb_command "next" "write" "gdb/strace/0-thr/$NONSTOP next write"
+
+#		read (fd[0], buf2, sizeof (buf2));
+gdb_command "next" "read" "gdb/strace/0-thr/$NONSTOP next read"
+
+#		vfork ();
+gdb_command "next" "vfork" "gdb/strace/0-thr/$NONSTOP next vfork"
+
+gdb_command "continue" "_exit" "gdb/strace/0-thr/$NONSTOP test exited"
+
+gdb_command "quit" "" ""
+close -i $gdb_spawn_id
+
+set infile [open [standard_output_file strace-$NONSTOP.out] r]
+set ok 0
+while { [gets $infile line] >= 0 } {
+    switch -regexp $line {
+	".*close\\(.*=" { incr ok }
+	".*chroot\\(.*=" { incr ok }
+	".*pipe\\(.*=" { incr ok }
+	".*write\\(.*=" { incr ok }
+	".*read\\(.*=" { incr ok }
+	".*vfork.*=" { incr ok }
+    }
+}
+switch $ok {
+    6 { pass  "gdb/strace/0-thr/$NONSTOP ($ok)" }
+    0 { unresolved "gdb/strace/0-thr/$NONSTOP ($ok)" }
+    default { fail "gdb/strace/0-thr/$NONSTOP ($ok)" }
+}
+
+cleanup_server_and_clients
+sleep 5
+
+close $infile
+
+# ----------------------------------------------------------------------
+
+verbose "##### Test coordination of a gdb client and an strace client 
with a threaded test"
+
+set res [gdbserver_start "--multi" ""]
+set gdbserver_protocol [lindex $res 0]
+set gdbserver_gdbport [lindex $res 1]
+
+start_client $testpath2 "$NONSTOP" "non-stop $NONSTOP"
+
+gdb_command "b main" "Breakpoint 1 at" "gdb/strace/1-thr/$NONSTOP b main"
+
+gdb_command "run" "Breakpoint 1," "gdb/strace/1-thr/$NONSTOP hit b main"
+
+set target_pid [get_target_pid $testfile2]
+
+set strace_spawn_id [start_strace "-f -e \!futex -G $gdbserver_gdbport 
-o [standard_output_file strace-gdb-$NONSTOP.out] -p $target_pid"]
+if { $strace_spawn_id == 0 || $strace_spawn_id == ""} {
+    return 0
+}
+
+gdb_command "b thread_worker" "Breakpoint 2 at" 
"gdb/strace/1-thr/$NONSTOP b thread_worker"
+gdb_command "continue" "Breakpoint 2" "gdb/strace/1-thr/$NONSTOP hit b 
thread_worker"
+
+# TODO needed, a reliable way to choose the desired thread
+gdb_command "thread 2" "" ""
+
+#		close (-1);
+set bp_location [gdb_get_line_number "close" "$srcfile2"]
+gdb_command "b $srcfile2:$bp_location" "Breakpoint 3" 
"gdb/strace/1-thr/$NONSTOP b close"
+gdb_command "continue" "Breakpoint 3" "gdb/strace/1-thr/$NONSTOP hit b 
close"
+gdb_command "next" "chroot" "gdb/strace/1-thr/$NONSTOP next close"
+
+#		chroot (".");
+gdb_command "next" "pipe" "gdb/strace/1-thr/$NONSTOP next chroot"
+
+#		pipe (fd);
+gdb_command "next" "write" "gdb/strace/1-thr/$NONSTOP next pipe"
+
+#		write (fd[1])
+gdb_command "next" "read" "gdb/strace/1-thr/$NONSTOP next write"
+
+#		read (fd[1])
+gdb_command "next" "syscall" "gdb/strace/1-thr/$NONSTOP next read"
+
+#		syscall (unknown_syscall)
+gdb_command "next" "\}" "gdb/strace/1-thr/$NONSTOP next syscall"
+
+gdb_command "quit" "" ""
+
+set infile [open [standard_output_file strace-gdb-$NONSTOP.out] r]
+set ok 0
+set have_clone 0
+while { [gets $infile line] >= 0 } {
+    switch -regexp $line {
+	".*clone\\(" { set have_clone 1 }
+	".*close\\(" { if { $have_clone } {incr ok;verbose "close"} }
+	".*chroot\\(" { if { $have_clone } {incr ok;verbose "chroot"} }
+	".*pipe\\(" { if { $have_clone } {incr ok;verbose "pipe"} }
+	".*write\\(" { if { $have_clone } {incr ok;verbose "write"} }
+	".*read\\(" { if { $have_clone } {incr ok;verbose "read"} }
+	".*syscall_[abcdefx0123456789]*\\(" { if { $have_clone } {incr 
ok;verbose "syscall"} }
+    }
+}
+switch $ok {
+    4 -
+    5 { xfail "gdb/strace/1-thr/$NONSTOP ($ok)" }
+    6 { pass  "gdb/strace/1-thr/$NONSTOP ($ok)" }
+    0 { unresolved "gdb/strace/1-thr/$NONSTOP ($ok)" }
+    default { fail "gdb/strace/1-thr/$NONSTOP ($ok)" }
+}
+
+cleanup_server_and_clients
+sleep 1
+
+# ----------------------------------------------------------------------
+
+verbose "##### Test an strace client with the threaded test"
+
+set res [gdbserver_start "--once" "$testpath2"]
+set gdbserver_protocol [lindex $res 0]
+set gdbserver_gdbport [lindex $res 1]
+sleep 1
+
+set target_pid [get_target_pid $testfile2]
+set strace_spawn_id [start_strace "-f -G $gdbserver_gdbport -o 
[standard_output_file strace-thr-$NONSTOP.out]"]
+if { $strace_spawn_id == 0 || $strace_spawn_id == ""} {
+     return 0
+}
+set ok 0
+expect {
+    -i $server_spawn_id -re {exited} { incr ok }
+}
+expect {
+    -i $strace_spawn_id -re {detached} { incr ok }
+}
+switch $ok {
+    2 { pass "gdbserver/strace" }
+    0 { fail "gdbserver/strace ($ok)" }
+}
+
+close -i $strace_spawn_id
+close $infile
+set infile [open [standard_output_file strace-thr-$NONSTOP.out] r]
+set ok 0
+set have_clone 0
+while { [gets $infile line] >= 0 } {
+    switch -regexp $line {
+	".*clone\\(" { set have_clone 1 }
+	".*close\\(" { if { $have_clone } {incr ok}}
+	".*chroot\\(" { if { $have_clone } {incr ok} }
+	".*pipe\\(" { if { $have_clone } {incr ok} }
+	".*write\\(" { if { $have_clone } {incr ok} }
+	".*read\\(" { if { $have_clone } {incr ok} }
+	".*syscall_[abcdefx0123456789]*\\(" { if { $have_clone } {incr ok} }
+    }
+}
+switch $ok {
+    6 { pass  "strace/0-thr/$NONSTOP ($ok)" }
+    0 { unresolved "strace/0-thr/$NONSTOP ($ok)" }
+    default { fail "strace/0-thr/$NONSTOP ($ok)" }
+}
+
+cleanup_server_and_clients
+close $infile
+sleep 5
+
+# ----------------------------------------------------------------------
+
+verbose "##### Test coordination of a gdb client and an strace client 
with a multithreaded test"
+
+set res [gdbserver_start "--multi" ""]
+set gdbserver_protocol [lindex $res 0]
+set gdbserver_gdbport [lindex $res 1]
+
+start_client $testpath2 "$NONSTOP" "multithread non-stop $NONSTOP"
+
+gdb_command "b main" "Breakpoint 1 at" "gdb/strace/2-thr/$NONSTOP b main"
+
+gdb_command "run 2" "Breakpoint 1," "gdb/strace/2-thr/$NONSTOP hit b main"
+
+set target_pid [get_target_pid $testfile2]
+
+set strace_spawn_id [start_strace "-f -e \!futex -G $gdbserver_gdbport 
-o [standard_output_file strace-gdb-multi-$NONSTOP.out] -p $target_pid"]
+if { $strace_spawn_id == 0 || $strace_spawn_id == ""} {
+    return 0
+}
+
+set bp_location [gdb_get_line_number "close" "$srcfile2"]
+gdb_command "b $srcfile2:$bp_location" "Breakpoint 2" 
"gdb/strace/2-thr/$NONSTOP b close"
+gdb_command "continue" "Breakpoint 2" "gdb/strace/2-thr/$NONSTOP hit b 
close"
+# TODO needed, a reliable way to choose the desired thread
+gdb_command "info thread" "" ""
+gdb_command "thread 2" "close" "gdb/strace/2-thr/$NONSTOP"
+
+#		close (-1);
+if { $NONSTOP == off} {
+    gdb_command "next" "" ""
+}
+gdb_command "next" "chroot" "gdb/strace/2-thr/$NONSTOP next close"
+
+#		chroot (".");
+gdb_command "next" "pipe" "gdb/strace/2-thr/$NONSTOP next chroot"
+
+#		pipe (fd);
+gdb_command "next" "write" "gdb/strace/2-thr/$NONSTOP next pipe"
+
+#		write (fd[1])
+gdb_command "next" "read" "gdb/strace/2-thr/$NONSTOP next write"
+
+#		read (fd[1])
+gdb_command "next" "syscall" "gdb/strace/2-thr/$NONSTOP next read"
+
+#		syscall (unknown_syscall)
+gdb_command "next" "\}" "gdb/strace/2-thr/$NONSTOP next syscall"
+
+gdb_command "thread 3" "Switching to thread" "gdb/strace/2-thr/$NONSTOP 
switch threads"
+
+# gdb_command "continue" "exited normally" "exited $NONSTOP"
+gdb_command "continue" "" ""
+
+gdb_command "quit" "" ""
+
+set infile [open [standard_output_file strace-gdb-multi-$NONSTOP.out] r]
+set ok 0
+set have_clone 0
+while { [gets $infile line] >= 0 } {
+    switch -regexp $line {
+	".*clone\\(" { set have_clone 1 }
+	".*close\\(" { if { $have_clone } {incr ok} }
+	".*chroot\\(" { if { $have_clone } {incr ok} }
+	".*pipe\\(" { if { $have_clone } {incr ok} }
+	".*write\\(" { if { $have_clone } {incr ok} }
+	".*read\\(" { if { $have_clone } {incr ok} }
+	".*syscall_[abcdefx0123456789]*\\(" { if { $have_clone } {incr ok} }
+    }
+}
+switch $ok {
+    0 { unresolved "gdb/strace/2-thr/$NONSTOP ($ok)" }
+    6 { pass  "gdb/strace/2-thr/$NONSTOP ($ok)" }
+    default { xfail "gdb/strace/2-thr/$NONSTOP ($ok)" }
+}
+
+cleanup_server_and_clients
+close $infile
+sleep 5
+
+# END foreach NONSTOP
+}
diff --git a/strace-threads.c b/strace-threads.c
new file mode 100644
index 00000000000..050377e1b4e
--- /dev/null
+++ b/strace-threads.c
@@ -0,0 +1,76 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/syscall.h>
+#include <errno.h>
+
+static pthread_barrier_t barrier;
+
+void *thread_worker ();
+
+
+int
+main(int argc, char *argv[])
+{
+  pthread_t *thread;
+  sigset_t mask1;
+  int thread_count;
+
+  if (argc == 1)
+    thread_count = 1;
+  else
+    {
+      thread_count = strtol(argv[1], NULL, 10);
+      if (errno != 0)
+	{
+	  perror("strtol");
+	  exit(EXIT_FAILURE);
+	}
+    }
+
+  thread = alloca (sizeof (pthread_t) * (thread_count + 1));
+  sigemptyset (&mask1);
+  sigaddset (&mask1, SIGUSR1);
+  sigprocmask (SIG_UNBLOCK, &mask1, NULL);
+
+  pthread_barrier_init (&barrier, NULL, thread_count);
+
+  for (int i = 1; i <= thread_count; i++)
+    pthread_create (&thread[i], NULL, & thread_worker, NULL);
+
+  for (int i = 1; i <= thread_count; i++)
+    pthread_join (thread[i], NULL);
+
+  exit (EXIT_SUCCESS);
+}
+
+void*
+thread_worker ()
+{
+  pthread_barrier_wait (&barrier);
+
+  int unknown_syscall = 123456789;
+  int fd[2];
+  char buf1[2] = "a";
+  char buf2[2];
+
+  close (-1);
+
+  chroot (".");
+
+  pipe (fd);
+
+  write (fd[1], buf1, sizeof (buf1));
+
+  read (fd[0], buf2, sizeof (buf2));
+
+  /* Test vfork-event interactions.  Child exits immediately.
+     (Plain fork won't work on no-mmu kernel configurations.)  */
+  //  if (vfork () == 0)
+  //    _exit (0);
+
+  syscall (unknown_syscall);
+}
+
