* linux-nat.h (linux_proc_get_tgid): Declare.
[deliverable/binutils-gdb.git] / gdb / linux-nat.c
index c511a7d19aa53a18113761dc1cf45e41075a90a2..c3aa94fe3ad848cf7ac76b2f76041ee96cd2ae1a 100644 (file)
@@ -89,48 +89,40 @@ notices it and returns.
 Waiting for events in async mode
 ================================
 
-In async mode, GDB should always be ready to handle both user input and target
-events, so neither blocking waitpid nor sigsuspend are viable
-options. Instead, we should notify the GDB main event loop whenever there's
-unprocessed event from the target.  The only way to notify this event loop is
-to make it wait on input from a pipe, and write something to the pipe whenever
-there's event. Obviously, if we fail to notify the event loop if there's
-target event, it's bad.  If we notify the event loop when there's no event
-from target, linux-nat.c will detect that there's no event, actually, and
-report event of type TARGET_WAITKIND_IGNORE, but it will waste time and
-better avoided.
-
-The main design point is that every time GDB is outside linux-nat.c, we have a
-SIGCHLD handler installed that is called when something happens to the target
-and notifies the GDB event loop. Also, the event is extracted from the target
-using waitpid and stored for future use.  Whenever GDB core decides to handle
-the event, and calls into linux-nat.c, we disable SIGCHLD and process things
-as in sync mode, except that before waitpid call we check if there are any
-previously read events.
-
-It could happen that during event processing, we'll try to get more events
-than there are events in the local queue, which will result to waitpid call.
-Those waitpid calls, while blocking, are guarantied to always have
-something for waitpid to return.  E.g., stopping a thread with SIGSTOP, and
-waiting for the lwp to stop.
-
-The event loop is notified about new events using a pipe. SIGCHLD handler does
-waitpid and writes the results in to a pipe. GDB event loop has the other end
-of the pipe among the sources. When event loop starts to process the event
-and calls a function in linux-nat.c, all events from the pipe are transferred
-into a local queue and SIGCHLD is blocked. Further processing goes as in sync
-mode. Before we return from linux_nat_wait, we transfer all unprocessed events
-from local queue back to the pipe, so that when we get back to event loop,
-event loop will notice there's something more to do.
-
-SIGCHLD is blocked when we're inside target_wait, so that should we actually
-want to wait for some more events, SIGCHLD handler does not steal them from
-us. Technically, it would be possible to add new events to the local queue but
-it's about the same amount of work as blocking SIGCHLD.
-
-This moving of events from pipe into local queue and back into pipe when we
-enter/leave linux-nat.c is somewhat ugly. Unfortunately, GDB event loop is
-home-grown and incapable to wait on any queue.
+In async mode, GDB should always be ready to handle both user input
+and target events, so neither blocking waitpid nor sigsuspend are
+viable options.  Instead, we should asynchronously notify the GDB main
+event loop whenever there's an unprocessed event from the target.  We
+detect asynchronous target events by handling SIGCHLD signals.  To
+notify the event loop about target events, the self-pipe trick is used
+--- a pipe is registered as waitable event source in the event loop,
+the event loop select/poll's on the read end of this pipe (as well on
+other event sources, e.g., stdin), and the SIGCHLD handler writes a
+byte to this pipe.  This is more portable than relying on
+pselect/ppoll, since on kernels that lack those syscalls, libc
+emulates them with select/poll+sigprocmask, and that is racy
+(a.k.a. plain broken).
+
+Obviously, if we fail to notify the event loop if there's a target
+event, it's bad.  OTOH, if we notify the event loop when there's no
+event from the target, linux_nat_wait will detect that there's no real
+event to report, and return event of type TARGET_WAITKIND_IGNORE.
+This is mostly harmless, but it will waste time and is better avoided.
+
+The main design point is that every time GDB is outside linux-nat.c,
+we have a SIGCHLD handler installed that is called when something
+happens to the target and notifies the GDB event loop.  Whenever GDB
+core decides to handle the event, and calls into linux-nat.c, we
+process things as in sync mode, except that the we never block in
+sigsuspend.
+
+While processing an event, we may end up momentarily blocked in
+waitpid calls.  Those waitpid calls, while blocking, are guarantied to
+return quickly.  E.g., in all-stop mode, before reporting to the core
+that an LWP hit a breakpoint, all LWPs are stopped by sending them
+SIGSTOP, and synchronously waiting for the SIGSTOP to be reported.
+Note that this is different from blocking indefinitely waiting for the
+next event --- here, we're already handling an event.
 
 Use of signals
 ==============
@@ -296,166 +288,55 @@ static int linux_nat_async_mask_value = 1;
    event loop.  */
 static int linux_nat_event_pipe[2] = { -1, -1 };
 
-/* Number of queued events in the pipe.  */
-static volatile int linux_nat_num_queued_events;
+/* Flush the event pipe.  */
 
-/* The possible SIGCHLD handling states.  */
-
-enum sigchld_state
-{
-  /* SIGCHLD disabled, with action set to sigchld_handler, for the
-     sigsuspend in linux_nat_wait.  */
-  sigchld_sync,
-  /* SIGCHLD enabled, with action set to async_sigchld_handler.  */
-  sigchld_async,
-  /* Set SIGCHLD to default action.  Used while creating an
-     inferior.  */
-  sigchld_default
-};
-
-/* The current SIGCHLD handling state.  */
-static enum sigchld_state linux_nat_async_events_state;
-
-static enum sigchld_state linux_nat_async_events (enum sigchld_state enable);
-static void pipe_to_local_event_queue (void);
-static void local_event_queue_to_pipe (void);
-static void linux_nat_event_pipe_push (int pid, int status, int options);
-static int linux_nat_event_pipe_pop (int* ptr_status, int* ptr_options);
-static void linux_nat_set_async_mode (int on);
-static void linux_nat_async (void (*callback)
-                            (enum inferior_event_type event_type, void *context),
-                            void *context);
-static int linux_nat_async_mask (int mask);
-static int kill_lwp (int lwpid, int signo);
-
-static int stop_callback (struct lwp_info *lp, void *data);
-
-/* Captures the result of a successful waitpid call, along with the
-   options used in that call.  */
-struct waitpid_result
-{
-  int pid;
-  int status;
-  int options;
-  struct waitpid_result *next;
-};
-
-/* A singly-linked list of the results of the waitpid calls performed
-   in the async SIGCHLD handler.  */
-static struct waitpid_result *waitpid_queue = NULL;
-
-/* Similarly to `waitpid', but check the local event queue instead of
-   querying the kernel queue.  If PEEK, don't remove the event found
-   from the queue.  */
-
-static int
-queued_waitpid_1 (int pid, int *status, int flags, int peek)
+static void
+async_file_flush (void)
 {
-  struct waitpid_result *msg = waitpid_queue, *prev = NULL;
-
-  if (debug_linux_nat_async)
-    fprintf_unfiltered (gdb_stdlog,
-                       "\
-QWPID: linux_nat_async_events_state(%d), linux_nat_num_queued_events(%d)\n",
-                       linux_nat_async_events_state,
-                       linux_nat_num_queued_events);
-
-  if (flags & __WALL)
-    {
-      for (; msg; prev = msg, msg = msg->next)
-       if (pid == -1 || pid == msg->pid)
-         break;
-    }
-  else if (flags & __WCLONE)
-    {
-      for (; msg; prev = msg, msg = msg->next)
-       if (msg->options & __WCLONE
-           && (pid == -1 || pid == msg->pid))
-         break;
-    }
-  else
-    {
-      for (; msg; prev = msg, msg = msg->next)
-       if ((msg->options & __WCLONE) == 0
-           && (pid == -1 || pid == msg->pid))
-         break;
-    }
+  int ret;
+  char buf;
 
-  if (msg)
+  do
     {
-      int pid;
-
-      if (status)
-       *status = msg->status;
-      pid = msg->pid;
-
-      if (debug_linux_nat_async)
-       fprintf_unfiltered (gdb_stdlog, "QWPID: pid(%d), status(%x)\n",
-                           pid, msg->status);
-
-      if (!peek)
-       {
-         if (prev)
-           prev->next = msg->next;
-         else
-           waitpid_queue = msg->next;
-
-         msg->next = NULL;
-         xfree (msg);
-       }
-
-      return pid;
+      ret = read (linux_nat_event_pipe[0], &buf, 1);
     }
-
-  if (debug_linux_nat_async)
-    fprintf_unfiltered (gdb_stdlog, "QWPID: miss\n");
-
-  if (status)
-    *status = 0;
-  return -1;
+  while (ret >= 0 || (ret == -1 && errno == EINTR));
 }
 
-/* Similarly to `waitpid', but check the local event queue.  */
-
-static int
-queued_waitpid (int pid, int *status, int flags)
-{
-  return queued_waitpid_1 (pid, status, flags, 0);
-}
+/* Put something (anything, doesn't matter what, or how much) in event
+   pipe, so that the select/poll in the event-loop realizes we have
+   something to process.  */
 
 static void
-push_waitpid (int pid, int status, int options)
+async_file_mark (void)
 {
-  struct waitpid_result *event, *new_event;
+  int ret;
 
-  new_event = xmalloc (sizeof (*new_event));
-  new_event->pid = pid;
-  new_event->status = status;
-  new_event->options = options;
-  new_event->next = NULL;
+  /* It doesn't really matter what the pipe contains, as long we end
+     up with something in it.  Might as well flush the previous
+     left-overs.  */
+  async_file_flush ();
 
-  if (waitpid_queue)
+  do
     {
-      for (event = waitpid_queue;
-          event && event->next;
-          event = event->next)
-       ;
-
-      event->next = new_event;
+      ret = write (linux_nat_event_pipe[1], "+", 1);
     }
-  else
-    waitpid_queue = new_event;
-}
+  while (ret == -1 && errno == EINTR);
 
-/* Drain all queued events of PID.  If PID is -1, the effect is of
-   draining all events.  */
-static void
-drain_queued_events (int pid)
-{
-  while (queued_waitpid (pid, NULL, __WALL) != -1)
-    ;
+  /* Ignore EAGAIN.  If the pipe is full, the event loop will already
+     be awakened anyway.  */
 }
 
+static void linux_nat_async (void (*callback)
+                            (enum inferior_event_type event_type, void *context),
+                            void *context);
+static int linux_nat_async_mask (int mask);
+static int kill_lwp (int lwpid, int signo);
+
+static int stop_callback (struct lwp_info *lp, void *data);
+
+static void block_child_signals (sigset_t *prev_mask);
+static void restore_child_signals_mask (sigset_t *prev_mask);
 \f
 /* Trivial list manipulation functions to keep track of a list of
    new stopped processes.  */
@@ -506,21 +387,13 @@ linux_tracefork_child (void)
   _exit (0);
 }
 
-/* Wrapper function for waitpid which handles EINTR, and checks for
-   locally queued events.  */
+/* Wrapper function for waitpid which handles EINTR.  */
 
 static int
 my_waitpid (int pid, int *status, int flags)
 {
   int ret;
 
-  /* There should be no concurrent calls to waitpid.  */
-  gdb_assert (linux_nat_async_events_state == sigchld_sync);
-
-  ret = queued_waitpid (pid, status, flags);
-  if (ret != -1)
-    return ret;
-
   do
     {
       ret = waitpid (pid, status, flags);
@@ -548,16 +421,20 @@ linux_test_for_tracefork (int original_pid)
 {
   int child_pid, ret, status;
   long second_pid;
-  enum sigchld_state async_events_original_state;
+  sigset_t prev_mask;
 
-  async_events_original_state = linux_nat_async_events (sigchld_sync);
+  /* We don't want those ptrace calls to be interrupted.  */
+  block_child_signals (&prev_mask);
 
   linux_supports_tracefork_flag = 0;
   linux_supports_tracevforkdone_flag = 0;
 
   ret = ptrace (PTRACE_SETOPTIONS, original_pid, 0, PTRACE_O_TRACEFORK);
   if (ret != 0)
-    return;
+    {
+      restore_child_signals_mask (&prev_mask);
+      return;
+    }
 
   child_pid = fork ();
   if (child_pid == -1)
@@ -581,7 +458,7 @@ linux_test_for_tracefork (int original_pid)
       if (ret != 0)
        {
          warning (_("linux_test_for_tracefork: failed to kill child"));
-         linux_nat_async_events (async_events_original_state);
+         restore_child_signals_mask (&prev_mask);
          return;
        }
 
@@ -592,7 +469,7 @@ linux_test_for_tracefork (int original_pid)
        warning (_("linux_test_for_tracefork: unexpected wait status 0x%x from "
                 "killed child"), status);
 
-      linux_nat_async_events (async_events_original_state);
+      restore_child_signals_mask (&prev_mask);
       return;
     }
 
@@ -633,7 +510,7 @@ linux_test_for_tracefork (int original_pid)
     warning (_("linux_test_for_tracefork: failed to kill child"));
   my_waitpid (child_pid, &status, 0);
 
-  linux_nat_async_events (async_events_original_state);
+  restore_child_signals_mask (&prev_mask);
 }
 
 /* Return non-zero iff we have tracefork functionality available.
@@ -696,13 +573,13 @@ linux_child_post_startup_inferior (ptid_t ptid)
 static int
 linux_child_follow_fork (struct target_ops *ops, int follow_child)
 {
+  sigset_t prev_mask;
   ptid_t last_ptid;
   struct target_waitstatus last_status;
   int has_vforked;
   int parent_pid, child_pid;
 
-  if (target_can_async_p ())
-    target_async (NULL, 0);
+  block_child_signals (&prev_mask);
 
   get_last_target_status (&last_ptid, &last_status);
   has_vforked = (last_status.kind == TARGET_WAITKIND_VFORKED);
@@ -716,11 +593,15 @@ linux_child_follow_fork (struct target_ops *ops, int follow_child)
       /* We're already attached to the parent, by default. */
 
       /* Before detaching from the child, remove all breakpoints from
-         it.  (This won't actually modify the breakpoint list, but will
-         physically remove the breakpoints from the child.) */
-      /* If we vforked this will remove the breakpoints from the parent
-        also, but they'll be reinserted below.  */
-      detach_breakpoints (child_pid);
+         it.  If we forked, then this has already been taken care of
+         by infrun.c.  If we vforked however, any breakpoint inserted
+         in the parent is visible in the child, even those added while
+         stopped in a vfork catchpoint.  This won't actually modify
+         the breakpoint list, but will physically remove the
+         breakpoints from the child.  This will remove the breakpoints
+         from the parent also, but they'll be reinserted below.  */
+      if (has_vforked)
+       detach_breakpoints (child_pid);
 
       /* Detach new forked process?  */
       if (detach_fork)
@@ -824,10 +705,6 @@ linux_child_follow_fork (struct target_ops *ops, int follow_child)
         breakpoint.  */
       last_tp->step_resume_breakpoint = NULL;
 
-      /* Needed to keep the breakpoint lists in sync.  */
-      if (! has_vforked)
-       detach_breakpoints (child_pid);
-
       /* Before detaching from the parent, remove all breakpoints from it. */
       remove_breakpoints ();
 
@@ -903,9 +780,7 @@ linux_child_follow_fork (struct target_ops *ops, int follow_child)
       follow_inferior_reset_breakpoints ();
     }
 
-  if (target_can_async_p ())
-    target_async (inferior_event_handler, 0);
-
+  restore_child_signals_mask (&prev_mask);
   return 0;
 }
 
@@ -966,9 +841,6 @@ linux_child_insert_exec_catchpoint (int pid)
 
 /* List of known LWPs.  */
 struct lwp_info *lwp_list;
-
-/* Number of LWPs in the list.  */
-static int num_lwps;
 \f
 
 /* Original signal mask.  */
@@ -978,14 +850,33 @@ static sigset_t normal_mask;
    _initialize_linux_nat.  */
 static sigset_t suspend_mask;
 
-/* SIGCHLD action for synchronous mode.  */
-struct sigaction sync_sigchld_action;
+/* Signals to block to make that sigsuspend work.  */
+static sigset_t blocked_mask;
+
+/* SIGCHLD action.  */
+struct sigaction sigchld_action;
 
-/* SIGCHLD action for asynchronous mode.  */
-static struct sigaction async_sigchld_action;
+/* Block child signals (SIGCHLD and linux threads signals), and store
+   the previous mask in PREV_MASK.  */
 
-/* SIGCHLD default action, to pass to new inferiors.  */
-static struct sigaction sigchld_default_action;
+static void
+block_child_signals (sigset_t *prev_mask)
+{
+  /* Make sure SIGCHLD is blocked.  */
+  if (!sigismember (&blocked_mask, SIGCHLD))
+    sigaddset (&blocked_mask, SIGCHLD);
+
+  sigprocmask (SIG_BLOCK, &blocked_mask, prev_mask);
+}
+
+/* Restore child signals mask, previously returned by
+   block_child_signals.  */
+
+static void
+restore_child_signals_mask (sigset_t *prev_mask)
+{
+  sigprocmask (SIG_SETMASK, prev_mask, NULL);
+}
 \f
 
 /* Prototypes for local functions.  */
@@ -1032,7 +923,48 @@ init_lwp_list (void)
     }
 
   lwp_list = NULL;
-  num_lwps = 0;
+}
+
+/* Remove all LWPs belong to PID from the lwp list.  */
+
+static void
+purge_lwp_list (int pid)
+{
+  struct lwp_info *lp, *lpprev, *lpnext;
+
+  lpprev = NULL;
+
+  for (lp = lwp_list; lp; lp = lpnext)
+    {
+      lpnext = lp->next;
+
+      if (ptid_get_pid (lp->ptid) == pid)
+       {
+         if (lp == lwp_list)
+           lwp_list = lp->next;
+         else
+           lpprev->next = lp->next;
+
+         xfree (lp);
+       }
+      else
+       lpprev = lp;
+    }
+}
+
+/* Return the number of known LWPs in the tgid given by PID.  */
+
+static int
+num_lwps (int pid)
+{
+  int count = 0;
+  struct lwp_info *lp;
+
+  for (lp = lwp_list; lp; lp = lp->next)
+    if (ptid_get_pid (lp->ptid) == pid)
+      count++;
+
+  return count;
 }
 
 /* Add the LWP specified by PID to the list.  Return a pointer to the
@@ -1056,9 +988,8 @@ add_lwp (ptid_t ptid)
 
   lp->next = lwp_list;
   lwp_list = lp;
-  ++num_lwps;
 
-  if (num_lwps > 1 && linux_nat_new_thread != NULL)
+  if (num_lwps (GET_PID (ptid)) > 1 && linux_nat_new_thread != NULL)
     linux_nat_new_thread (ptid);
 
   return lp;
@@ -1080,8 +1011,6 @@ delete_lwp (ptid_t ptid)
   if (!lp)
     return;
 
-  num_lwps--;
-
   if (lpprev)
     lpprev->next = lp->next;
   else
@@ -1111,21 +1040,54 @@ find_lwp_pid (ptid_t ptid)
   return NULL;
 }
 
+/* Returns true if PTID matches filter FILTER.  FILTER can be the wild
+   card MINUS_ONE_PTID (all ptid match it); can be a ptid representing
+   a process (ptid_is_pid returns true), in which case, all lwps of
+   that give process match, lwps of other process do not; or, it can
+   represent a specific thread, in which case, only that thread will
+   match true.  PTID must represent an LWP, it can never be a wild
+   card.  */
+
+static int
+ptid_match (ptid_t ptid, ptid_t filter)
+{
+  /* Since both parameters have the same type, prevent easy mistakes
+     from happening.  */
+  gdb_assert (!ptid_equal (ptid, minus_one_ptid)
+             && !ptid_equal (ptid, null_ptid));
+
+  if (ptid_equal (filter, minus_one_ptid))
+    return 1;
+  if (ptid_is_pid (filter)
+      && ptid_get_pid (ptid) == ptid_get_pid (filter))
+    return 1;
+  else if (ptid_equal (ptid, filter))
+    return 1;
+
+  return 0;
+}
+
 /* Call CALLBACK with its second argument set to DATA for every LWP in
    the list.  If CALLBACK returns 1 for a particular LWP, return a
    pointer to the structure describing that LWP immediately.
    Otherwise return NULL.  */
 
 struct lwp_info *
-iterate_over_lwps (int (*callback) (struct lwp_info *, void *), void *data)
+iterate_over_lwps (ptid_t filter,
+                  int (*callback) (struct lwp_info *, void *),
+                  void *data)
 {
   struct lwp_info *lp, *lpnext;
 
   for (lp = lwp_list; lp; lp = lpnext)
     {
       lpnext = lp->next;
-      if ((*callback) (lp, data))
-       return lp;
+
+      if (ptid_match (lp->ptid, filter))
+       {
+         if ((*callback) (lp, data))
+           return lp;
+       }
     }
 
   return NULL;
@@ -1167,6 +1129,34 @@ exit_lwp (struct lwp_info *lp)
   delete_lwp (lp->ptid);
 }
 
+/* Return an lwp's tgid, found in `/proc/PID/status'.  */
+
+int
+linux_proc_get_tgid (int lwpid)
+{
+  FILE *status_file;
+  char buf[100];
+  int tgid = -1;
+
+  snprintf (buf, sizeof (buf), "/proc/%d/status", (int) lwpid);
+  status_file = fopen (buf, "r");
+  if (status_file != NULL)
+    {
+      while (fgets (buf, sizeof (buf), status_file))
+       {
+         if (strncmp (buf, "Tgid:", 5) == 0)
+           {
+             tgid = strtoul (buf + strlen ("Tgid:"), NULL, 10);
+             break;
+           }
+       }
+
+      fclose (status_file);
+    }
+
+  return tgid;
+}
+
 /* Detect `T (stopped)' in `/proc/PID/status'.
    Other states including `T (tracing stop)' are reported as false.  */
 
@@ -1269,11 +1259,11 @@ int
 lin_lwp_attach_lwp (ptid_t ptid)
 {
   struct lwp_info *lp;
-  enum sigchld_state async_events_original_state;
+  sigset_t prev_mask;
 
   gdb_assert (is_lwp (ptid));
 
-  async_events_original_state = linux_nat_async_events (sigchld_sync);
+  block_child_signals (&prev_mask);
 
   lp = find_lwp_pid (ptid);
 
@@ -1296,6 +1286,7 @@ lin_lwp_attach_lwp (ptid_t ptid)
             to create them.  */
          warning (_("Can't attach %s: %s"), target_pid_to_str (ptid),
                   safe_strerror (errno));
+         restore_child_signals_mask (&prev_mask);
          return -1;
        }
 
@@ -1338,7 +1329,7 @@ lin_lwp_attach_lwp (ptid_t ptid)
       lp->stopped = 1;
     }
 
-  linux_nat_async_events (async_events_original_state);
+  restore_child_signals_mask (&prev_mask);
   return 0;
 }
 
@@ -1359,20 +1350,6 @@ linux_nat_create_inferior (struct target_ops *ops,
     /* Mask async mode.  Creating a child requires a loop calling
        wait_for_inferior currently.  */
     saved_async = linux_nat_async_mask (0);
-  else
-    {
-      /* Restore the original signal mask.  */
-      sigprocmask (SIG_SETMASK, &normal_mask, NULL);
-      /* Make sure we don't block SIGCHLD during a sigsuspend.  */
-      suspend_mask = normal_mask;
-      sigdelset (&suspend_mask, SIGCHLD);
-    }
-
-  /* Set SIGCHLD to the default action, until after execing the child,
-     since the inferior inherits the superior's signal mask.  It will
-     be blocked again in linux_nat_wait, which is only reached after
-     the inferior execing.  */
-  linux_nat_async_events (sigchld_default);
 
 #ifdef HAVE_PERSONALITY
   if (disable_randomization)
@@ -1415,19 +1392,8 @@ linux_nat_attach (struct target_ops *ops, char *args, int from_tty)
   int status;
   ptid_t ptid;
 
-  /* FIXME: We should probably accept a list of process id's, and
-     attach all of them.  */
   linux_ops->to_attach (ops, args, from_tty);
 
-  if (!target_can_async_p ())
-    {
-      /* Restore the original signal mask.  */
-      sigprocmask (SIG_SETMASK, &normal_mask, NULL);
-      /* Make sure we don't block SIGCHLD during a sigsuspend.  */
-      suspend_mask = normal_mask;
-      sigdelset (&suspend_mask, SIGCHLD);
-    }
-
   /* The ptrace base target adds the main thread with (pid,0,0)
      format.  Decorate it with lwp info.  */
   ptid = BUILD_LWP (GET_PID (inferior_ptid), GET_PID (inferior_ptid));
@@ -1447,18 +1413,10 @@ linux_nat_attach (struct target_ops *ops, char *args, int from_tty)
                        "LNA: waitpid %ld, saving status %s\n",
                        (long) GET_PID (lp->ptid), status_to_str (status));
 
-  if (!target_can_async_p ())
-    lp->status = status;
-  else
-    {
-      /* We already waited for this LWP, so put the wait result on the
-        pipe.  The event loop will wake up and gets us to handling
-        this event.  */
-      linux_nat_event_pipe_push (GET_PID (lp->ptid), status,
-                                lp->cloned ? __WCLONE : 0);
-      /* Register in the event loop.  */
-      target_async (inferior_event_handler, 0);
-    }
+  lp->status = status;
+
+  if (target_can_async_p ())
+    target_async (inferior_event_handler, 0);
 }
 
 /* Get pending status of LP.  */
@@ -1471,10 +1429,9 @@ get_pending_status (struct lwp_info *lp, int *status)
   get_last_target_status (&last_ptid, &last);
 
   /* If this lwp is the ptid that GDB is processing an event from, the
-     signal will be in stop_signal.  Otherwise, in all-stop + sync
-     mode, we may cache pending events in lp->status while trying to
-     stop all threads (see stop_wait_callback).  In async mode, the
-     events are always cached in waitpid_queue.  */
+     signal will be in stop_signal.  Otherwise, we may cache pending
+     events in lp->status while trying to stop all threads (see
+     stop_wait_callback).  */
 
   *status = 0;
 
@@ -1490,14 +1447,7 @@ get_pending_status (struct lwp_info *lp, int *status)
             stop_wait_callback sequence (see linux_nat_detach for
             example) --- we can only have pending events in the local
             queue.  */
-         if (queued_waitpid (GET_LWP (lp->ptid), status, __WALL) != -1)
-           {
-             if (WIFSTOPPED (*status))
-               signo = target_signal_from_host (WSTOPSIG (*status));
-
-             /* If not stopped, then the lwp is gone, no use in
-                resending a signal.  */
-           }
+         signo = target_signal_from_host (WSTOPSIG (lp->status));
        }
       else
        {
@@ -1539,8 +1489,6 @@ GPT: lwp %s had signal %s, but it is in no pass state\n",
              && signal_pass_state (tp->stop_signal))
            *status = W_STOPCODE (target_signal_to_host (tp->stop_signal));
        }
-      else if (target_can_async_p ())
-       queued_waitpid (GET_LWP (lp->ptid), status, __WALL);
       else
        *status = lp->status;
     }
@@ -1589,7 +1537,7 @@ detach_callback (struct lwp_info *lp, void *data)
        fprintf_unfiltered (gdb_stdlog,
                            "PTRACE_DETACH (%s, %s, 0) (OK)\n",
                            target_pid_to_str (lp->ptid),
-                           strsignal (WSTOPSIG (lp->status)));
+                           strsignal (WSTOPSIG (status)));
 
       delete_lwp (lp->ptid);
     }
@@ -1603,25 +1551,30 @@ linux_nat_detach (struct target_ops *ops, char *args, int from_tty)
   int pid;
   int status;
   enum target_signal sig;
+  struct lwp_info *main_lwp;
+
+  pid = GET_PID (inferior_ptid);
 
   if (target_can_async_p ())
     linux_nat_async (NULL, 0);
 
   /* Stop all threads before detaching.  ptrace requires that the
      thread is stopped to sucessfully detach.  */
-  iterate_over_lwps (stop_callback, NULL);
+  iterate_over_lwps (pid_to_ptid (pid), stop_callback, NULL);
   /* ... and wait until all of them have reported back that
      they're no longer running.  */
-  iterate_over_lwps (stop_wait_callback, NULL);
+  iterate_over_lwps (pid_to_ptid (pid), stop_wait_callback, NULL);
 
-  iterate_over_lwps (detach_callback, NULL);
+  iterate_over_lwps (pid_to_ptid (pid), detach_callback, NULL);
 
   /* Only the initial process should be left right now.  */
-  gdb_assert (num_lwps == 1);
+  gdb_assert (num_lwps (GET_PID (inferior_ptid)) == 1);
+
+  main_lwp = find_lwp_pid (pid_to_ptid (pid));
 
   /* Pass on any pending signal for the last LWP.  */
   if ((args == NULL || *args == '\0')
-      && get_pending_status (lwp_list, &status) != -1
+      && get_pending_status (main_lwp, &status) != -1
       && WIFSTOPPED (status))
     {
       /* Put the signal number in ARGS so that inf_ptrace_detach will
@@ -1631,16 +1584,10 @@ linux_nat_detach (struct target_ops *ops, char *args, int from_tty)
       fprintf_unfiltered (gdb_stdlog,
                          "LND: Sending signal %s to %s\n",
                          args,
-                         target_pid_to_str (lwp_list->ptid));
+                         target_pid_to_str (main_lwp->ptid));
     }
 
-  /* Destroy LWP info; it's no longer valid.  */
-  init_lwp_list ();
-
-  pid = ptid_get_pid (inferior_ptid);
-
-  if (target_can_async_p ())
-    drain_queued_events (pid);
+  delete_lwp (main_lwp->ptid);
 
   if (forks_exist_p ())
     {
@@ -1664,6 +1611,11 @@ resume_callback (struct lwp_info *lp, void *data)
 {
   if (lp->stopped && lp->status == 0)
     {
+      if (debug_linux_nat)
+       fprintf_unfiltered (gdb_stdlog,
+                           "RC:  PTRACE_CONT %s, 0, 0 (resuming sibling)\n",
+                           target_pid_to_str (lp->ptid));
+
       linux_ops->to_resume (linux_ops,
                            pid_to_ptid (GET_LWP (lp->ptid)),
                            0, TARGET_SIGNAL_0);
@@ -1703,8 +1655,9 @@ static void
 linux_nat_resume (struct target_ops *ops,
                  ptid_t ptid, int step, enum target_signal signo)
 {
+  sigset_t prev_mask;
   struct lwp_info *lp;
-  int resume_all;
+  int resume_many;
 
   if (debug_linux_nat)
     fprintf_unfiltered (gdb_stdlog,
@@ -1714,42 +1667,32 @@ linux_nat_resume (struct target_ops *ops,
                        signo ? strsignal (signo) : "0",
                        target_pid_to_str (inferior_ptid));
 
-  if (target_can_async_p ())
-    /* Block events while we're here.  */
-    linux_nat_async_events (sigchld_sync);
+  block_child_signals (&prev_mask);
 
   /* A specific PTID means `step only this process id'.  */
-  resume_all = (PIDGET (ptid) == -1);
-
-  if (non_stop && resume_all)
-    internal_error (__FILE__, __LINE__,
-                   "can't resume all in non-stop mode");
+  resume_many = (ptid_equal (minus_one_ptid, ptid)
+                || ptid_is_pid (ptid));
 
   if (!non_stop)
     {
-      if (resume_all)
-       iterate_over_lwps (resume_set_callback, NULL);
-      else
-       iterate_over_lwps (resume_clear_callback, NULL);
+      /* Mark the lwps we're resuming as resumed.  */
+      iterate_over_lwps (minus_one_ptid, resume_clear_callback, NULL);
+      iterate_over_lwps (ptid, resume_set_callback, NULL);
     }
+  else
+    iterate_over_lwps (minus_one_ptid, resume_set_callback, NULL);
 
-  /* If PID is -1, it's the current inferior that should be
-     handled specially.  */
-  if (PIDGET (ptid) == -1)
-    ptid = inferior_ptid;
-
-  lp = find_lwp_pid (ptid);
+  /* See if it's the current inferior that should be handled
+     specially.  */
+  if (resume_many)
+    lp = find_lwp_pid (inferior_ptid);
+  else
+    lp = find_lwp_pid (ptid);
   gdb_assert (lp != NULL);
 
-  /* Convert to something the lower layer understands.  */
-  ptid = pid_to_ptid (GET_LWP (lp->ptid));
-
   /* Remember if we're stepping.  */
   lp->step = step;
 
-  /* Mark this LWP as resumed.  */
-  lp->resumed = 1;
-
   /* If we have a pending wait status for this thread, there is no
      point in resuming the process.  But first make sure that
      linux_nat_wait won't preemptively handle the event - we
@@ -1758,16 +1701,12 @@ linux_nat_resume (struct target_ops *ops,
      other threads.  This bit of code needs to be synchronized
      with linux_nat_wait.  */
 
-  /* In async mode, we never have pending wait status.  */
-  if (target_can_async_p () && lp->status)
-    internal_error (__FILE__, __LINE__, "Pending status in async mode");
-
   if (lp->status && WIFSTOPPED (lp->status))
     {
       int saved_signo;
       struct inferior *inf;
 
-      inf = find_inferior_pid (ptid_get_pid (ptid));
+      inf = find_inferior_pid (ptid_get_pid (lp->ptid));
       gdb_assert (inf);
       saved_signo = target_signal_from_host (WSTOPSIG (lp->status));
 
@@ -1802,6 +1741,13 @@ linux_nat_resume (struct target_ops *ops,
                            "LLR: Short circuiting for status 0x%x\n",
                            lp->status);
 
+      restore_child_signals_mask (&prev_mask);
+      if (target_can_async_p ())
+       {
+         target_async (inferior_event_handler, 0);
+         /* Tell the event loop we have something to process.  */
+         async_file_mark ();
+       }
       return;
     }
 
@@ -1809,8 +1755,11 @@ linux_nat_resume (struct target_ops *ops,
      resume_callback.  */
   lp->stopped = 0;
 
-  if (resume_all)
-    iterate_over_lwps (resume_callback, NULL);
+  if (resume_many)
+    iterate_over_lwps (ptid, resume_callback, NULL);
+
+  /* Convert to something the lower layer understands.  */
+  ptid = pid_to_ptid (GET_LWP (lp->ptid));
 
   linux_ops->to_resume (linux_ops, ptid, step, signo);
   memset (&lp->siginfo, 0, sizeof (lp->siginfo));
@@ -1822,6 +1771,7 @@ linux_nat_resume (struct target_ops *ops,
                        target_pid_to_str (ptid),
                        signo ? strsignal (signo) : "0");
 
+  restore_child_signals_mask (&prev_mask);
   if (target_can_async_p ())
     target_async (inferior_event_handler, 0);
 }
@@ -1903,7 +1853,7 @@ linux_handle_extended_wait (struct lwp_info *lp, int status,
          struct cleanup *old_chain;
 
          ourstatus->kind = TARGET_WAITKIND_IGNORE;
-         new_lp = add_lwp (BUILD_LWP (new_pid, GET_PID (inferior_ptid)));
+         new_lp = add_lwp (BUILD_LWP (new_pid, GET_PID (lp->ptid)));
          new_lp->cloned = 1;
          new_lp->stopped = 1;
 
@@ -2247,40 +2197,21 @@ stop_wait_callback (struct lwp_info *lp, void *data)
                 there are any more (we still want to get that SIGSTOP). */
              stop_wait_callback (lp, NULL);
 
-             if (target_can_async_p ())
-               {
-                 /* Don't leave a pending wait status in async mode.
-                    Retrigger the breakpoint.  */
-                 if (!cancel_breakpoint (lp))
-                   {
-                     /* There was no gdb breakpoint set at pc.  Put
-                        the event back in the queue.  */
-                     if (debug_linux_nat)
-                       fprintf_unfiltered (gdb_stdlog, "\
-SWC: leaving SIGTRAP in local queue of %s\n", target_pid_to_str (lp->ptid));
-                     push_waitpid (GET_LWP (lp->ptid),
-                                   W_STOPCODE (SIGTRAP),
-                                   lp->cloned ? __WCLONE : 0);
-                   }
-               }
-             else
+             /* Hold the SIGTRAP for handling by linux_nat_wait.  If
+                there's another event, throw it back into the
+                queue. */
+             if (lp->status)
                {
-                 /* Hold the SIGTRAP for handling by
-                    linux_nat_wait. */
-                 /* If there's another event, throw it back into the
-                    queue. */
-                 if (lp->status)
-                   {
-                     if (debug_linux_nat)
-                       fprintf_unfiltered (gdb_stdlog,
-                                           "SWC: kill %s, %s\n",
-                                           target_pid_to_str (lp->ptid),
-                                           status_to_str ((int) status));
-                     kill_lwp (GET_LWP (lp->ptid), WSTOPSIG (lp->status));
-                   }
-                 /* Save the sigtrap event. */
-                 lp->status = status;
+                 if (debug_linux_nat)
+                   fprintf_unfiltered (gdb_stdlog,
+                                       "SWC: kill %s, %s\n",
+                                       target_pid_to_str (lp->ptid),
+                                       status_to_str ((int) status));
+                 kill_lwp (GET_LWP (lp->ptid), WSTOPSIG (lp->status));
                }
+
+             /* Save the sigtrap event. */
+             lp->status = status;
              return 0;
            }
          else
@@ -2311,7 +2242,7 @@ SWC: leaving SIGTRAP in local queue of %s\n", target_pid_to_str (lp->ptid));
              /* If the lp->status field is still empty, use it to
                 hold this event.  If not, then this event must be
                 returned to the event queue of the LWP.  */
-             if (lp->status || target_can_async_p ())
+             if (lp->status)
                {
                  if (debug_linux_nat)
                    {
@@ -2346,7 +2277,12 @@ status_callback (struct lwp_info *lp, void *data)
 {
   /* Only report a pending wait status if we pretend that this has
      indeed been resumed.  */
-  return (lp->status != 0 && lp->resumed);
+  /* We check for lp->waitstatus in addition to lp->status, because we
+     can have pending process exits recorded in lp->waitstatus, and
+     W_EXITCODE(0,0) == 0.  */
+  return ((lp->status != 0
+          || lp->waitstatus.kind != TARGET_WAITKIND_IGNORE)
+         && lp->resumed);
 }
 
 /* Return non-zero if LP isn't stopped.  */
@@ -2468,7 +2404,7 @@ cancel_breakpoints_callback (struct lwp_info *lp, void *data)
 /* Select one LWP out of those that have events pending.  */
 
 static void
-select_event_lwp (struct lwp_info **orig_lp, int *status)
+select_event_lwp (ptid_t filter, struct lwp_info **orig_lp, int *status)
 {
   int num_events = 0;
   int random_selector;
@@ -2478,7 +2414,8 @@ select_event_lwp (struct lwp_info **orig_lp, int *status)
   (*orig_lp)->status = *status;
 
   /* Give preference to any LWP that is being single-stepped.  */
-  event_lp = iterate_over_lwps (select_singlestep_lwp_callback, NULL);
+  event_lp = iterate_over_lwps (filter,
+                               select_singlestep_lwp_callback, NULL);
   if (event_lp != NULL)
     {
       if (debug_linux_nat)
@@ -2492,7 +2429,7 @@ select_event_lwp (struct lwp_info **orig_lp, int *status)
          which have had SIGTRAP events.  */
 
       /* First see how many SIGTRAP events we have.  */
-      iterate_over_lwps (count_events_callback, &num_events);
+      iterate_over_lwps (filter, count_events_callback, &num_events);
 
       /* Now randomly pick a LWP out of those that have had a SIGTRAP.  */
       random_selector = (int)
@@ -2503,7 +2440,8 @@ select_event_lwp (struct lwp_info **orig_lp, int *status)
                            "SEL: Found %d SIGTRAP events, selecting #%d\n",
                            num_events, random_selector);
 
-      event_lp = iterate_over_lwps (select_event_lwp_callback,
+      event_lp = iterate_over_lwps (filter,
+                                   select_event_lwp_callback,
                                    &random_selector);
     }
 
@@ -2621,7 +2559,8 @@ linux_nat_filter_event (int lwpid, int status, int options)
     }
 
   /* Check if the thread has exited.  */
-  if ((WIFEXITED (status) || WIFSIGNALED (status)) && num_lwps > 1)
+  if ((WIFEXITED (status) || WIFSIGNALED (status))
+      && num_lwps (GET_PID (lp->ptid)) > 1)
     {
       /* If this is the main thread, we must stop all threads and verify
         if they are still alive.  This is because in the nptl thread model
@@ -2632,11 +2571,12 @@ linux_nat_filter_event (int lwpid, int status, int options)
         if they have exited we can determine whether this signal
         should be ignored or whether it means the end of the debugged
         application, regardless of which threading model is being
-        used.  */
+        used.  */
       if (GET_PID (lp->ptid) == GET_LWP (lp->ptid))
        {
          lp->stopped = 1;
-         iterate_over_lwps (stop_and_resume_callback, NULL);
+         iterate_over_lwps (pid_to_ptid (GET_PID (lp->ptid)),
+                            stop_and_resume_callback, NULL);
        }
 
       if (debug_linux_nat)
@@ -2644,7 +2584,7 @@ linux_nat_filter_event (int lwpid, int status, int options)
                            "LLW: %s exited.\n",
                            target_pid_to_str (lp->ptid));
 
-      if (num_lwps > 1)
+      if (num_lwps (GET_PID (lp->ptid)) > 1)
        {
         /* If there is at least one more LWP, then the exit signal
            was not the end of the debugged application and should be
@@ -2658,8 +2598,10 @@ linux_nat_filter_event (int lwpid, int status, int options)
      thread model, LWPs other than the main thread do not issue
      signals when they exit so we must check whenever the thread has
      stopped.  A similar check is made in stop_wait_callback().  */
-  if (num_lwps > 1 && !linux_thread_alive (lp->ptid))
+  if (num_lwps (GET_PID (lp->ptid)) > 1 && !linux_thread_alive (lp->ptid))
     {
+      ptid_t ptid = pid_to_ptid (GET_PID (lp->ptid));
+
       if (debug_linux_nat)
        fprintf_unfiltered (gdb_stdlog,
                            "LLW: %s exited.\n",
@@ -2668,7 +2610,7 @@ linux_nat_filter_event (int lwpid, int status, int options)
       exit_lwp (lp);
 
       /* Make sure there is at least one thread running.  */
-      gdb_assert (iterate_over_lwps (running_callback, NULL));
+      gdb_assert (iterate_over_lwps (ptid, running_callback, NULL));
 
       /* Discard the event.  */
       return NULL;
@@ -2740,60 +2682,15 @@ linux_nat_filter_event (int lwpid, int status, int options)
   return lp;
 }
 
-/* Get the events stored in the pipe into the local queue, so they are
-   accessible to queued_waitpid.  We need to do this, since it is not
-   always the case that the event at the head of the pipe is the event
-   we want.  */
-
-static void
-pipe_to_local_event_queue (void)
-{
-  if (debug_linux_nat_async)
-    fprintf_unfiltered (gdb_stdlog,
-                       "PTLEQ: linux_nat_num_queued_events(%d)\n",
-                       linux_nat_num_queued_events);
-  while (linux_nat_num_queued_events)
-    {
-      int lwpid, status, options;
-      lwpid = linux_nat_event_pipe_pop (&status, &options);
-      gdb_assert (lwpid > 0);
-      push_waitpid (lwpid, status, options);
-    }
-}
-
-/* Get the unprocessed events stored in the local queue back into the
-   pipe, so the event loop realizes there's something else to
-   process.  */
-
-static void
-local_event_queue_to_pipe (void)
-{
-  struct waitpid_result *w = waitpid_queue;
-  while (w)
-    {
-      struct waitpid_result *next = w->next;
-      linux_nat_event_pipe_push (w->pid,
-                                w->status,
-                                w->options);
-      xfree (w);
-      w = next;
-    }
-  waitpid_queue = NULL;
-
-  if (debug_linux_nat_async)
-    fprintf_unfiltered (gdb_stdlog,
-                       "LEQTP: linux_nat_num_queued_events(%d)\n",
-                       linux_nat_num_queued_events);
-}
-
 static ptid_t
-linux_nat_wait (struct target_ops *ops,
-               ptid_t ptid, struct target_waitstatus *ourstatus)
+linux_nat_wait_1 (struct target_ops *ops,
+                 ptid_t ptid, struct target_waitstatus *ourstatus)
 {
+  static sigset_t prev_mask;
   struct lwp_info *lp = NULL;
   int options = 0;
   int status = 0;
-  pid_t pid = PIDGET (ptid);
+  pid_t pid;
 
   if (debug_linux_nat_async)
     fprintf_unfiltered (gdb_stdlog, "LLW: enter\n");
@@ -2801,10 +2698,8 @@ linux_nat_wait (struct target_ops *ops,
   /* The first time we get here after starting a new inferior, we may
      not have added it to the LWP list yet - this is the earliest
      moment at which we know its PID.  */
-  if (num_lwps == 0)
+  if (ptid_is_pid (inferior_ptid))
     {
-      gdb_assert (!is_lwp (inferior_ptid));
-
       /* Upgrade the main thread's ptid.  */
       thread_change_ptid (inferior_ptid,
                          BUILD_LWP (GET_PID (inferior_ptid),
@@ -2814,25 +2709,34 @@ linux_nat_wait (struct target_ops *ops,
       lp->resumed = 1;
     }
 
-  /* Block events while we're here.  */
-  linux_nat_async_events (sigchld_sync);
+  /* Make sure SIGCHLD is blocked.  */
+  block_child_signals (&prev_mask);
+
+  if (ptid_equal (ptid, minus_one_ptid))
+    pid = -1;
+  else if (ptid_is_pid (ptid))
+    /* A request to wait for a specific tgid.  This is not possible
+       with waitpid, so instead, we wait for any child, and leave
+       children we're not interested in right now with a pending
+       status to report later.  */
+    pid = -1;
+  else
+    pid = GET_LWP (ptid);
 
 retry:
+  lp = NULL;
+  status = 0;
 
   /* Make sure there is at least one LWP that has been resumed.  */
-  gdb_assert (iterate_over_lwps (resumed_callback, NULL));
+  gdb_assert (iterate_over_lwps (ptid, resumed_callback, NULL));
 
   /* First check if there is a LWP with a wait status pending.  */
   if (pid == -1)
     {
       /* Any LWP that's been resumed will do.  */
-      lp = iterate_over_lwps (status_callback, NULL);
+      lp = iterate_over_lwps (ptid, status_callback, NULL);
       if (lp)
        {
-         if (target_can_async_p ())
-           internal_error (__FILE__, __LINE__,
-                           "Found an LWP with a pending status in async mode.");
-
          status = lp->status;
          lp->status = 0;
 
@@ -2844,8 +2748,8 @@ retry:
        }
 
       /* But if we don't find one, we'll have to wait, and check both
-         cloned and uncloned processes.  We start with the cloned
-         processes.  */
+        cloned and uncloned processes.  We start with the cloned
+        processes.  */
       options = __WCLONE | WNOHANG;
     }
   else if (is_lwp (ptid))
@@ -2872,9 +2776,16 @@ retry:
          the layer beneath us can understand.  */
       options = lp->cloned ? __WCLONE : 0;
       pid = GET_LWP (ptid);
+
+      /* We check for lp->waitstatus in addition to lp->status,
+        because we can have pending process exits recorded in
+        lp->status and W_EXITCODE(0,0) == 0.  We should probably have
+        an additional lp->status_p flag.  */
+      if (status == 0 && lp->waitstatus.kind == TARGET_WAITKIND_IGNORE)
+       lp = NULL;
     }
 
-  if (status && lp->signalled)
+  if (lp && lp->signalled)
     {
       /* A pending SIGSTOP may interfere with the normal stream of
          events.  In a typical case where interference is a problem,
@@ -2908,16 +2819,14 @@ retry:
       set_sigint_trap ();
     }
 
-  while (status == 0)
+  if (target_can_async_p ())
+    options |= WNOHANG; /* In async mode, don't block.  */
+
+  while (lp == NULL)
     {
       pid_t lwpid;
 
-      if (target_can_async_p ())
-       /* In async mode, don't ever block.  Only look at the locally
-          queued events.  */
-       lwpid = queued_waitpid (pid, &status, options);
-      else
-       lwpid = my_waitpid (pid, &status, options);
+      lwpid = my_waitpid (pid, &status, options);
 
       if (lwpid > 0)
        {
@@ -2931,14 +2840,79 @@ retry:
            }
 
          lp = linux_nat_filter_event (lwpid, status, options);
-         if (!lp)
+
+         if (lp
+             && ptid_is_pid (ptid)
+             && ptid_get_pid (lp->ptid) != ptid_get_pid (ptid))
            {
-             /* A discarded event.  */
-             status = 0;
+             if (debug_linux_nat)
+               fprintf (stderr, "LWP %ld got an event %06x, leaving pending.\n",
+                        ptid_get_lwp (lp->ptid), status);
+
+             if (WIFSTOPPED (status))
+               {
+                 if (WSTOPSIG (status) != SIGSTOP)
+                   {
+                     lp->status = status;
+
+                     stop_callback (lp, NULL);
+
+                     /* Resume in order to collect the sigstop.  */
+                     ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0);
+
+                     stop_wait_callback (lp, NULL);
+                   }
+                 else
+                   {
+                     lp->stopped = 1;
+                     lp->signalled = 0;
+                   }
+               }
+             else if (WIFEXITED (status) || WIFSIGNALED (status))
+               {
+                 if (debug_linux_nat)
+                   fprintf (stderr, "Process %ld exited while stopping LWPs\n",
+                            ptid_get_lwp (lp->ptid));
+
+                 /* This was the last lwp in the process.  Since
+                    events are serialized to GDB core, and we can't
+                    report this one right now, but GDB core and the
+                    other target layers will want to be notified
+                    about the exit code/signal, leave the status
+                    pending for the next time we're able to report
+                    it.  */
+                 lp->status = status;
+
+                 /* Prevent trying to stop this thread again.  We'll
+                    never try to resume it because it has a pending
+                    status.  */
+                 lp->stopped = 1;
+
+                 /* Dead LWP's aren't expected to reported a pending
+                    sigstop.  */
+                 lp->signalled = 0;
+
+                 /* Store the pending event in the waitstatus as
+                    well, because W_EXITCODE(0,0) == 0.  */
+                 store_waitstatus (&lp->waitstatus, status);
+               }
+
+             /* Keep looking.  */
+             lp = NULL;
              continue;
            }
 
-         break;
+         if (lp)
+           break;
+         else
+           {
+             if (pid == -1)
+               {
+                 /* waitpid did return something.  Restart over.  */
+                 options |= __WCLONE;
+               }
+             continue;
+           }
        }
 
       if (pid == -1)
@@ -2956,12 +2930,10 @@ retry:
                  /* No interesting event.  */
                  ourstatus->kind = TARGET_WAITKIND_IGNORE;
 
-                 /* Get ready for the next event.  */
-                 target_async (inferior_event_handler, 0);
-
                  if (debug_linux_nat_async)
                    fprintf_unfiltered (gdb_stdlog, "LLW: exit (ignore)\n");
 
+                 restore_child_signals_mask (&prev_mask);
                  return minus_one_ptid;
                }
 
@@ -2970,7 +2942,7 @@ retry:
        }
 
       /* We shouldn't end up here unless we want to try again.  */
-      gdb_assert (status == 0);
+      gdb_assert (lp == NULL);
     }
 
   if (!target_can_async_p ())
@@ -3019,7 +2991,6 @@ retry:
                                target_pid_to_str (lp->ptid),
                                signo ? strsignal (signo) : "0");
          lp->stopped = 0;
-         status = 0;
          goto retry;
        }
 
@@ -3035,7 +3006,8 @@ retry:
                 will receive it - unless they're using CLONE_THREAD to
                 share signals.  Since we only want to report it once, we
                 mark it as ignored for all LWPs except this one.  */
-             iterate_over_lwps (set_ignore_sigint, NULL);
+             iterate_over_lwps (pid_to_ptid (ptid_get_pid (ptid)),
+                                             set_ignore_sigint, NULL);
              lp->ignore_sigint = 0;
            }
          else
@@ -3053,24 +3025,24 @@ retry:
   if (!non_stop)
     {
       /* Now stop all other LWP's ...  */
-      iterate_over_lwps (stop_callback, NULL);
+      iterate_over_lwps (minus_one_ptid, stop_callback, NULL);
 
       /* ... and wait until all of them have reported back that
         they're no longer running.  */
-      iterate_over_lwps (stop_wait_callback, NULL);
+      iterate_over_lwps (minus_one_ptid, stop_wait_callback, NULL);
 
       /* If we're not waiting for a specific LWP, choose an event LWP
         from among those that have had events.  Giving equal priority
         to all LWPs that have had events helps prevent
         starvation.  */
       if (pid == -1)
-       select_event_lwp (&lp, &status);
+       select_event_lwp (ptid, &lp, &status);
     }
 
   /* Now that we've selected our final event LWP, cancel any
      breakpoints in other LWPs that have hit a GDB breakpoint.  See
      the comment in cancel_breakpoints_callback to find out why.  */
-  iterate_over_lwps (cancel_breakpoints_callback, lp);
+  iterate_over_lwps (minus_one_ptid, cancel_breakpoints_callback, lp);
 
   if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP)
     {
@@ -3088,16 +3060,43 @@ retry:
   else
     store_waitstatus (ourstatus, status);
 
-  /* Get ready for the next event.  */
-  if (target_can_async_p ())
-    target_async (inferior_event_handler, 0);
-
   if (debug_linux_nat_async)
     fprintf_unfiltered (gdb_stdlog, "LLW: exit\n");
 
+  restore_child_signals_mask (&prev_mask);
   return lp->ptid;
 }
 
+static ptid_t
+linux_nat_wait (struct target_ops *ops,
+               ptid_t ptid, struct target_waitstatus *ourstatus)
+{
+  ptid_t event_ptid;
+
+  if (debug_linux_nat)
+    fprintf_unfiltered (gdb_stdlog, "linux_nat_wait: [%s]\n", target_pid_to_str (ptid));
+
+  /* Flush the async file first.  */
+  if (target_can_async_p ())
+    async_file_flush ();
+
+  event_ptid = linux_nat_wait_1 (ops, ptid, ourstatus);
+
+  /* If we requested any event, and something came out, assume there
+     may be more.  If we requested a specific lwp or process, also
+     assume there may be more.  */
+  if (target_can_async_p ()
+      && (ourstatus->kind != TARGET_WAITKIND_IGNORE
+         || !ptid_equal (ptid, minus_one_ptid)))
+    async_file_mark ();
+
+  /* Get ready for the next event.  */
+  if (target_can_async_p ())
+    target_async (inferior_event_handler, 0);
+
+  return event_ptid;
+}
+
 static int
 kill_callback (struct lwp_info *lp, void *data)
 {
@@ -3174,9 +3173,6 @@ linux_nat_kill (struct target_ops *ops)
   ptid_t last_ptid;
   int status;
 
-  if (target_can_async_p ())
-    target_async (NULL, 0);
-
   /* If we're stopped while forking and we haven't followed yet,
      kill the other task.  We need to do this first because the
      parent will be sleeping if this is a vfork.  */
@@ -3191,24 +3187,22 @@ linux_nat_kill (struct target_ops *ops)
     }
 
   if (forks_exist_p ())
-    {
-      linux_fork_killall ();
-      drain_queued_events (-1);
-    }
+    linux_fork_killall ();
   else
     {
+      ptid_t ptid = pid_to_ptid (ptid_get_pid (inferior_ptid));
       /* Stop all threads before killing them, since ptrace requires
         that the thread is stopped to sucessfully PTRACE_KILL.  */
-      iterate_over_lwps (stop_callback, NULL);
+      iterate_over_lwps (ptid, stop_callback, NULL);
       /* ... and wait until all of them have reported back that
         they're no longer running.  */
-      iterate_over_lwps (stop_wait_callback, NULL);
+      iterate_over_lwps (ptid, stop_wait_callback, NULL);
 
       /* Kill all LWP's ...  */
-      iterate_over_lwps (kill_callback, NULL);
+      iterate_over_lwps (ptid, kill_callback, NULL);
 
       /* ... and wait until we've flushed all events.  */
-      iterate_over_lwps (kill_wait_callback, NULL);
+      iterate_over_lwps (ptid, kill_wait_callback, NULL);
     }
 
   target_mourn_inferior ();
@@ -3217,16 +3211,11 @@ linux_nat_kill (struct target_ops *ops)
 static void
 linux_nat_mourn_inferior (struct target_ops *ops)
 {
-  /* Destroy LWP info; it's no longer valid.  */
-  init_lwp_list ();
+  purge_lwp_list (ptid_get_pid (inferior_ptid));
 
   if (! forks_exist_p ())
-    {
-      /* Normal case, no other forks available.  */
-      if (target_can_async_p ())
-       linux_nat_async (NULL, 0);
-      linux_ops->to_mourn_inferior (ops);
-    }
+    /* Normal case, no other forks available.  */
+    linux_ops->to_mourn_inferior (ops);
   else
     /* Multi-fork case.  The current inferior_ptid has exited, but
        there are other viable forks to debug.  Delete the exiting
@@ -3261,8 +3250,6 @@ linux_xfer_siginfo (struct target_ops *ops, enum target_object object,
                     const char *annex, gdb_byte *readbuf,
                    const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
 {
-  struct lwp_info *lp;
-  LONGEST n;
   int pid;
   struct siginfo siginfo;
   gdb_byte inf_siginfo[sizeof (struct siginfo)];
@@ -3372,8 +3359,8 @@ linux_nat_pid_to_str (struct target_ops *ops, ptid_t ptid)
   static char buf[64];
 
   if (is_lwp (ptid)
-      && ((lwp_list && lwp_list->next)
-         || GET_PID (ptid) != GET_LWP (ptid)))
+      && (GET_PID (ptid) != GET_LWP (ptid)
+         || num_lwps (GET_PID (ptid)) > 1))
     {
       snprintf (buf, sizeof (buf), "LWP %ld", GET_LWP (ptid));
       return buf;
@@ -3382,21 +3369,6 @@ linux_nat_pid_to_str (struct target_ops *ops, ptid_t ptid)
   return normal_pid_to_str (ptid);
 }
 
-static void
-sigchld_handler (int signo)
-{
-  if (target_async_permitted
-      && linux_nat_async_events_state != sigchld_sync
-      && signo == SIGCHLD)
-    /* It is *always* a bug to hit this.  */
-    internal_error (__FILE__, __LINE__,
-                   "sigchld_handler called when async events are enabled");
-
-  /* Do nothing.  The only reason for this handler is that it allows
-     us to use sigsuspend in linux_nat_wait above to wait for the
-     arrival of a SIGCHLD.  */
-}
-
 /* Accepts an integer PID; Returns a string representing a file that
    can be opened to get the symbols for the child process.  */
 
@@ -3663,6 +3635,7 @@ linux_nat_make_corefile_notes (bfd *obfd, int *note_size)
   char psargs[80] = { '\0' };
   char *note_data = NULL;
   ptid_t current_ptid = inferior_ptid;
+  ptid_t filter = pid_to_ptid (ptid_get_pid (inferior_ptid));
   gdb_byte *auxv;
   int auxv_len;
 
@@ -3696,7 +3669,7 @@ linux_nat_make_corefile_notes (bfd *obfd, int *note_size)
   thread_args.note_size = note_size;
   thread_args.num_notes = 0;
   thread_args.stop_signal = find_stop_signal ();
-  iterate_over_lwps (linux_nat_corefile_thread_callback, &thread_args);
+  iterate_over_lwps (filter, linux_nat_corefile_thread_callback, &thread_args);
   gdb_assert (thread_args.num_notes != 0);
   note_data = thread_args.note_data;
 
@@ -4304,12 +4277,13 @@ static int
 linux_nat_is_async_p (void)
 {
   /* NOTE: palves 2008-03-21: We're only async when the user requests
-     it explicitly with the "maintenance set target-async" command.
+     it explicitly with the "set target-async" command.
      Someday, linux will always be async.  */
   if (!target_async_permitted)
     return 0;
 
-  return 1;
+  /* See target.h/target_async_mask.  */
+  return linux_nat_async_mask_value;
 }
 
 /* target_can_async_p implementation.  */
@@ -4318,7 +4292,7 @@ static int
 linux_nat_can_async_p (void)
 {
   /* NOTE: palves 2008-03-21: We're only async when the user requests
-     it explicitly with the "maintenance set target-async" command.
+     it explicitly with the "set target-async" command.
      Someday, linux will always be async.  */
   if (!target_async_permitted)
     return 0;
@@ -4333,208 +4307,46 @@ linux_nat_supports_non_stop (void)
   return 1;
 }
 
-/* target_async_mask implementation.  */
-
-static int
-linux_nat_async_mask (int mask)
-{
-  int current_state;
-  current_state = linux_nat_async_mask_value;
+/* True if we want to support multi-process.  To be removed when GDB
+   supports multi-exec.  */
 
-  if (current_state != mask)
-    {
-      if (mask == 0)
-       {
-         linux_nat_async (NULL, 0);
-         linux_nat_async_mask_value = mask;
-       }
-      else
-       {
-         linux_nat_async_mask_value = mask;
-         linux_nat_async (inferior_event_handler, 0);
-       }
-    }
-
-  return current_state;
-}
-
-/* Pop an event from the event pipe.  */
+int linux_multi_process = 0;
 
 static int
-linux_nat_event_pipe_pop (int* ptr_status, int* ptr_options)
+linux_nat_supports_multi_process (void)
 {
-  struct waitpid_result event = {0};
-  int ret;
-
-  do
-    {
-      ret = read (linux_nat_event_pipe[0], &event, sizeof (event));
-    }
-  while (ret == -1 && errno == EINTR);
-
-  gdb_assert (ret == sizeof (event));
-
-  *ptr_status = event.status;
-  *ptr_options = event.options;
-
-  linux_nat_num_queued_events--;
-
-  return event.pid;
+  return linux_multi_process;
 }
 
-/* Push an event into the event pipe.  */
-
-static void
-linux_nat_event_pipe_push (int pid, int status, int options)
-{
-  int ret;
-  struct waitpid_result event = {0};
-  event.pid = pid;
-  event.status = status;
-  event.options = options;
-
-  do
-    {
-      ret = write (linux_nat_event_pipe[1], &event, sizeof (event));
-      gdb_assert ((ret == -1 && errno == EINTR) || ret == sizeof (event));
-    } while (ret == -1 && errno == EINTR);
-
-  linux_nat_num_queued_events++;
-}
+/* target_async_mask implementation.  */
 
-static void
-get_pending_events (void)
+static int
+linux_nat_async_mask (int new_mask)
 {
-  int status, options, pid;
-
-  if (!target_async_permitted
-      || linux_nat_async_events_state != sigchld_async)
-    internal_error (__FILE__, __LINE__,
-                   "get_pending_events called with async masked");
+  int curr_mask = linux_nat_async_mask_value;
 
-  while (1)
+  if (curr_mask != new_mask)
     {
-      status = 0;
-      options = __WCLONE | WNOHANG;
-
-      do
+      if (new_mask == 0)
        {
-         pid = waitpid (-1, &status, options);
-       }
-      while (pid == -1 && errno == EINTR);
-
-      if (pid <= 0)
-       {
-         options = WNOHANG;
-         do
-           {
-             pid = waitpid (-1, &status, options);
-           }
-         while (pid == -1 && errno == EINTR);
+         linux_nat_async (NULL, 0);
+         linux_nat_async_mask_value = new_mask;
        }
-
-      if (pid <= 0)
-       /* No more children reporting events.  */
-       break;
-
-      if (debug_linux_nat_async)
-       fprintf_unfiltered (gdb_stdlog, "\
-get_pending_events: pid(%d), status(%x), options (%x)\n",
-                           pid, status, options);
-
-      linux_nat_event_pipe_push (pid, status, options);
-    }
-
-  if (debug_linux_nat_async)
-    fprintf_unfiltered (gdb_stdlog, "\
-get_pending_events: linux_nat_num_queued_events(%d)\n",
-                       linux_nat_num_queued_events);
-}
-
-/* SIGCHLD handler for async mode.  */
-
-static void
-async_sigchld_handler (int signo)
-{
-  if (debug_linux_nat_async)
-    fprintf_unfiltered (gdb_stdlog, "async_sigchld_handler\n");
-
-  get_pending_events ();
-}
-
-/* Set SIGCHLD handling state to STATE.  Returns previous state.  */
-
-static enum sigchld_state
-linux_nat_async_events (enum sigchld_state state)
-{
-  enum sigchld_state current_state = linux_nat_async_events_state;
-
-  if (debug_linux_nat_async)
-    fprintf_unfiltered (gdb_stdlog,
-                       "LNAE: state(%d): linux_nat_async_events_state(%d), "
-                       "linux_nat_num_queued_events(%d)\n",
-                       state, linux_nat_async_events_state,
-                       linux_nat_num_queued_events);
-
-  if (current_state != state)
-    {
-      sigset_t mask;
-      sigemptyset (&mask);
-      sigaddset (&mask, SIGCHLD);
-
-      /* Always block before changing state.  */
-      sigprocmask (SIG_BLOCK, &mask, NULL);
-
-      /* Set new state.  */
-      linux_nat_async_events_state = state;
-
-      switch (state)
+      else
        {
-       case sigchld_sync:
-         {
-           /* Block target events.  */
-           sigprocmask (SIG_BLOCK, &mask, NULL);
-           sigaction (SIGCHLD, &sync_sigchld_action, NULL);
-           /* Get events out of queue, and make them available to
-              queued_waitpid / my_waitpid.  */
-           pipe_to_local_event_queue ();
-         }
-         break;
-       case sigchld_async:
-         {
-           /* Unblock target events for async mode.  */
-
-           sigprocmask (SIG_BLOCK, &mask, NULL);
-
-           /* Put events we already waited on, in the pipe first, so
-              events are FIFO.  */
-           local_event_queue_to_pipe ();
-           /* While in masked async, we may have not collected all
-              the pending events.  Get them out now.  */
-           get_pending_events ();
-
-           /* Let'em come.   */
-           sigaction (SIGCHLD, &async_sigchld_action, NULL);
-           sigprocmask (SIG_UNBLOCK, &mask, NULL);
-         }
-         break;
-       case sigchld_default:
-         {
-           /* SIGCHLD default mode.  */
-           sigaction (SIGCHLD, &sigchld_default_action, NULL);
+         linux_nat_async_mask_value = new_mask;
 
-           /* Get events out of queue, and make them available to
-              queued_waitpid / my_waitpid.  */
-           pipe_to_local_event_queue ();
-
-           /* Unblock SIGCHLD.  */
-           sigprocmask (SIG_UNBLOCK, &mask, NULL);
-         }
-         break;
+         /* If we're going out of async-mask in all-stop, then the
+            inferior is stopped.  The next resume will call
+            target_async.  In non-stop, the target event source
+            should be always registered in the event loop.  Do so
+            now.  */
+         if (non_stop)
+           linux_nat_async (inferior_event_handler, 0);
        }
     }
 
-  return current_state;
+  return curr_mask;
 }
 
 static int async_terminal_is_ours = 1;
@@ -4599,10 +4411,69 @@ static void (*async_client_callback) (enum inferior_event_type event_type,
                                      void *context);
 static void *async_client_context;
 
+/* SIGCHLD handler that serves two purposes: In non-stop/async mode,
+   so we notice when any child changes state, and notify the
+   event-loop; it allows us to use sigsuspend in linux_nat_wait_1
+   above to wait for the arrival of a SIGCHLD.  */
+
+static void
+sigchld_handler (int signo)
+{
+  int old_errno = errno;
+
+  if (debug_linux_nat_async)
+    fprintf_unfiltered (gdb_stdlog, "sigchld\n");
+
+  if (signo == SIGCHLD
+      && linux_nat_event_pipe[0] != -1)
+    async_file_mark (); /* Let the event loop know that there are
+                          events to handle.  */
+
+  errno = old_errno;
+}
+
+/* Callback registered with the target events file descriptor.  */
+
 static void
-linux_nat_async_file_handler (int error, gdb_client_data client_data)
+handle_target_event (int error, gdb_client_data client_data)
 {
-  async_client_callback (INF_REG_EVENT, async_client_context);
+  (*async_client_callback) (INF_REG_EVENT, async_client_context);
+}
+
+/* Create/destroy the target events pipe.  Returns previous state.  */
+
+static int
+linux_async_pipe (int enable)
+{
+  int previous = (linux_nat_event_pipe[0] != -1);
+
+  if (previous != enable)
+    {
+      sigset_t prev_mask;
+
+      block_child_signals (&prev_mask);
+
+      if (enable)
+       {
+         if (pipe (linux_nat_event_pipe) == -1)
+           internal_error (__FILE__, __LINE__,
+                           "creating event pipe failed.");
+
+         fcntl (linux_nat_event_pipe[0], F_SETFL, O_NONBLOCK);
+         fcntl (linux_nat_event_pipe[1], F_SETFL, O_NONBLOCK);
+       }
+      else
+       {
+         close (linux_nat_event_pipe[0]);
+         close (linux_nat_event_pipe[1]);
+         linux_nat_event_pipe[0] = -1;
+         linux_nat_event_pipe[1] = -1;
+       }
+
+      restore_child_signals_mask (&prev_mask);
+    }
+
+  return previous;
 }
 
 /* target_async implementation.  */
@@ -4619,18 +4490,21 @@ linux_nat_async (void (*callback) (enum inferior_event_type event_type,
     {
       async_client_callback = callback;
       async_client_context = context;
-      add_file_handler (linux_nat_event_pipe[0],
-                       linux_nat_async_file_handler, NULL);
-
-      linux_nat_async_events (sigchld_async);
+      if (!linux_async_pipe (1))
+       {
+         add_file_handler (linux_nat_event_pipe[0],
+                           handle_target_event, NULL);
+         /* There may be pending events to handle.  Tell the event loop
+            to poll them.  */
+         async_file_mark ();
+       }
     }
   else
     {
       async_client_callback = callback;
       async_client_context = context;
-
-      linux_nat_async_events (sigchld_sync);
       delete_file_handler (linux_nat_event_pipe[0]);
+      linux_async_pipe (0);
     }
   return;
 }
@@ -4641,68 +4515,48 @@ linux_nat_async (void (*callback) (enum inferior_event_type event_type,
 static int
 linux_nat_stop_lwp (struct lwp_info *lwp, void *data)
 {
-  ptid_t ptid = * (ptid_t *) data;
-
-  if (ptid_equal (lwp->ptid, ptid)
-      || ptid_equal (minus_one_ptid, ptid)
-      || (ptid_is_pid (ptid)
-         && ptid_get_pid (ptid) == ptid_get_pid (lwp->ptid)))
+  if (!lwp->stopped)
     {
-      if (!lwp->stopped)
-       {
-         int pid, status;
+      int pid, status;
+      ptid_t ptid = lwp->ptid;
 
-         if (debug_linux_nat)
-           fprintf_unfiltered (gdb_stdlog,
-                               "LNSL: running -> suspending %s\n",
-                               target_pid_to_str (lwp->ptid));
-
-         /* Peek once, to check if we've already waited for this
-            LWP.  */
-         pid = queued_waitpid_1 (ptid_get_lwp (lwp->ptid), &status,
-                                 lwp->cloned ? __WCLONE : 0,  1 /* peek */);
+      if (debug_linux_nat)
+       fprintf_unfiltered (gdb_stdlog,
+                           "LNSL: running -> suspending %s\n",
+                           target_pid_to_str (lwp->ptid));
 
-         if (pid == -1)
-           {
-             ptid_t ptid = lwp->ptid;
 
-             stop_callback (lwp, NULL);
-             stop_wait_callback (lwp, NULL);
+      stop_callback (lwp, NULL);
+      stop_wait_callback (lwp, NULL);
 
-             /* If the lwp exits while we try to stop it, there's
-                nothing else to do.  */
-             lwp = find_lwp_pid (ptid);
-             if (lwp == NULL)
-               return 0;
+      /* If the lwp exits while we try to stop it, there's nothing
+        else to do.  */
+      lwp = find_lwp_pid (ptid);
+      if (lwp == NULL)
+       return 0;
 
-             pid = queued_waitpid_1 (ptid_get_lwp (lwp->ptid), &status,
-                                     lwp->cloned ? __WCLONE : 0,
-                                     1 /* peek */);
-           }
+      /* If we didn't collect any signal other than SIGSTOP while
+        stopping the LWP, push a SIGNAL_0 event.  In either case, the
+        event-loop will end up calling target_wait which will collect
+        these.  */
+      if (lwp->status == 0)
+       lwp->status = W_STOPCODE (0);
+      async_file_mark ();
+    }
+  else
+    {
+      /* Already known to be stopped; do nothing.  */
 
-         /* If we didn't collect any signal other than SIGSTOP while
-            stopping the LWP, push a SIGNAL_0 event.  In either case,
-            the event-loop will end up calling target_wait which will
-            collect these.  */
-         if (pid == -1)
-           push_waitpid (ptid_get_lwp (lwp->ptid), W_STOPCODE (0),
-                         lwp->cloned ? __WCLONE : 0);
-       }
-      else
+      if (debug_linux_nat)
        {
-         /* Already known to be stopped; do nothing.  */
-
-         if (debug_linux_nat)
-           {
-             if (find_thread_pid (lwp->ptid)->stop_requested)
-               fprintf_unfiltered (gdb_stdlog, "\
+         if (find_thread_pid (lwp->ptid)->stop_requested)
+           fprintf_unfiltered (gdb_stdlog, "\
 LNSL: already stopped/stop_requested %s\n",
-                                   target_pid_to_str (lwp->ptid));
-             else
-               fprintf_unfiltered (gdb_stdlog, "\
+                               target_pid_to_str (lwp->ptid));
+         else
+           fprintf_unfiltered (gdb_stdlog, "\
 LNSL: already stopped/no stop_requested yet %s\n",
-                                   target_pid_to_str (lwp->ptid));
-           }
+                               target_pid_to_str (lwp->ptid));
        }
     }
   return 0;
@@ -4712,15 +4566,25 @@ static void
 linux_nat_stop (ptid_t ptid)
 {
   if (non_stop)
-    {
-      linux_nat_async_events (sigchld_sync);
-      iterate_over_lwps (linux_nat_stop_lwp, &ptid);
-      target_async (inferior_event_handler, 0);
-    }
+    iterate_over_lwps (ptid, linux_nat_stop_lwp, NULL);
   else
     linux_ops->to_stop (ptid);
 }
 
+static void
+linux_nat_close (int quitting)
+{
+  /* Unregister from the event loop.  */
+  if (target_is_async_p ())
+    target_async (NULL, 0);
+
+  /* Reset the async_masking.  */
+  linux_nat_async_mask_value = 1;
+
+  if (linux_ops->to_close)
+    linux_ops->to_close (quitting);
+}
+
 void
 linux_nat_add_target (struct target_ops *t)
 {
@@ -4751,10 +4615,13 @@ linux_nat_add_target (struct target_ops *t)
   t->to_async_mask = linux_nat_async_mask;
   t->to_terminal_inferior = linux_nat_terminal_inferior;
   t->to_terminal_ours = linux_nat_terminal_ours;
+  t->to_close = linux_nat_close;
 
   /* Methods for non-stop support.  */
   t->to_stop = linux_nat_stop;
 
+  t->to_supports_multi_process = linux_nat_supports_multi_process;
+
   /* We don't change the stratum; this target will sit at
      process_stratum and thread_db will set at thread_stratum.  This
      is a little strange, since this is a multi-threaded-capable
@@ -4798,18 +4665,6 @@ linux_nat_get_siginfo (ptid_t ptid)
   return &lp->siginfo;
 }
 
-/* Enable/Disable async mode.  */
-
-static void
-linux_nat_setup_async (void)
-{
-  if (pipe (linux_nat_event_pipe) == -1)
-    internal_error (__FILE__, __LINE__,
-                   "creating event pipe failed.");
-  fcntl (linux_nat_event_pipe[0], F_SETFL, O_NONBLOCK);
-  fcntl (linux_nat_event_pipe[1], F_SETFL, O_NONBLOCK);
-}
-
 /* Provide a prototype to silence -Wmissing-prototypes.  */
 extern initialize_file_ftype _initialize_linux_nat;
 
@@ -4845,38 +4700,22 @@ Enables printf debugging output."),
                            show_debug_linux_nat_async,
                            &setdebuglist, &showdebuglist);
 
-  /* Get the default SIGCHLD action.  Used while forking an inferior
-     (see linux_nat_create_inferior/linux_nat_async_events).  */
-  sigaction (SIGCHLD, NULL, &sigchld_default_action);
-
-  /* Block SIGCHLD by default.  Doing this early prevents it getting
-     unblocked if an exception is thrown due to an error while the
-     inferior is starting (sigsetjmp/siglongjmp).  */
-  sigemptyset (&mask);
-  sigaddset (&mask, SIGCHLD);
-  sigprocmask (SIG_BLOCK, &mask, NULL);
-
   /* Save this mask as the default.  */
   sigprocmask (SIG_SETMASK, NULL, &normal_mask);
 
-  /* The synchronous SIGCHLD handler.  */
-  sync_sigchld_action.sa_handler = sigchld_handler;
-  sigemptyset (&sync_sigchld_action.sa_mask);
-  sync_sigchld_action.sa_flags = SA_RESTART;
+  /* Install a SIGCHLD handler.  */
+  sigchld_action.sa_handler = sigchld_handler;
+  sigemptyset (&sigchld_action.sa_mask);
+  sigchld_action.sa_flags = SA_RESTART;
 
   /* Make it the default.  */
-  sigaction (SIGCHLD, &sync_sigchld_action, NULL);
+  sigaction (SIGCHLD, &sigchld_action, NULL);
 
   /* Make sure we don't block SIGCHLD during a sigsuspend.  */
   sigprocmask (SIG_SETMASK, NULL, &suspend_mask);
   sigdelset (&suspend_mask, SIGCHLD);
 
-  /* SIGCHLD handler for async mode.  */
-  async_sigchld_action.sa_handler = async_sigchld_handler;
-  sigemptyset (&async_sigchld_action.sa_mask);
-  async_sigchld_action.sa_flags = SA_RESTART;
-
-  linux_nat_setup_async ();
+  sigemptyset (&blocked_mask);
 
   add_setshow_boolean_cmd ("disable-randomization", class_support,
                           &disable_randomization, _("\
@@ -4923,7 +4762,6 @@ lin_thread_get_thread_signals (sigset_t *set)
 {
   struct sigaction action;
   int restart, cancel;
-  sigset_t blocked_mask;
 
   sigemptyset (&blocked_mask);
   sigemptyset (set);
This page took 0.048974 seconds and 4 git commands to generate.