gdb/
[deliverable/binutils-gdb.git] / gdb / linux-nat.c
index 33b13fad5bae8f6dc52a2d221f663257270f2a6b..b82c2485d04187365e6710d24c2cdde8235c531b 100644 (file)
@@ -1901,7 +1901,7 @@ linux_nat_detach (struct target_ops *ops, char *args, int from_tty)
 /* Resume LP.  */
 
 static void
-resume_lwp (struct lwp_info *lp, int step)
+resume_lwp (struct lwp_info *lp, int step, enum gdb_signal signo)
 {
   if (lp->stopped)
     {
@@ -1919,14 +1919,18 @@ resume_lwp (struct lwp_info *lp, int step)
        {
          if (debug_linux_nat)
            fprintf_unfiltered (gdb_stdlog,
-                               "RC:  PTRACE_CONT %s, 0, 0 (resuming sibling)\n",
-                               target_pid_to_str (lp->ptid));
+                               "RC: Resuming sibling %s, %s, %s\n",
+                               target_pid_to_str (lp->ptid),
+                               (signo != GDB_SIGNAL_0
+                                ? strsignal (gdb_signal_to_host (signo))
+                                : "0"),
+                               step ? "step" : "resume");
 
          if (linux_nat_prepare_to_resume != NULL)
            linux_nat_prepare_to_resume (lp);
          linux_ops->to_resume (linux_ops,
                                pid_to_ptid (GET_LWP (lp->ptid)),
-                               step, GDB_SIGNAL_0);
+                               step, signo);
          lp->stopped = 0;
          lp->step = step;
          memset (&lp->siginfo, 0, sizeof (lp->siginfo));
@@ -1949,10 +1953,27 @@ resume_lwp (struct lwp_info *lp, int step)
     }
 }
 
+/* Resume LWP, with the last stop signal, if it is in pass state.  */
+
 static int
-resume_callback (struct lwp_info *lp, void *data)
+linux_nat_resume_callback (struct lwp_info *lp, void *data)
 {
-  resume_lwp (lp, 0);
+  enum gdb_signal signo = GDB_SIGNAL_0;
+
+  if (lp->stopped)
+    {
+      struct thread_info *thread;
+
+      thread = find_thread_ptid (lp->ptid);
+      if (thread != NULL)
+       {
+         if (signal_pass_state (thread->suspend.stop_signal))
+           signo = thread->suspend.stop_signal;
+         thread->suspend.stop_signal = GDB_SIGNAL_0;
+       }
+    }
+
+  resume_lwp (lp, 0, signo);
   return 0;
 }
 
@@ -2059,11 +2080,11 @@ linux_nat_resume (struct target_ops *ops,
     }
 
   /* Mark LWP as not stopped to prevent it from being continued by
-     resume_callback.  */
+     linux_nat_resume_callback.  */
   lp->stopped = 0;
 
   if (resume_many)
-    iterate_over_lwps (ptid, resume_callback, NULL);
+    iterate_over_lwps (ptid, linux_nat_resume_callback, NULL);
 
   /* Convert to something the lower layer understands.  */
   ptid = pid_to_ptid (GET_LWP (lp->ptid));
@@ -2881,110 +2902,39 @@ stop_wait_callback (struct lwp_info *lp, void *data)
 
       if (WSTOPSIG (status) != SIGSTOP)
        {
-         if (linux_nat_status_is_event (status))
-           {
-             /* If a LWP other than the LWP that we're reporting an
-                event for has hit a GDB breakpoint (as opposed to
-                some random trap signal), then just arrange for it to
-                hit it again later.  We don't keep the SIGTRAP status
-                and don't forward the SIGTRAP signal to the LWP.  We
-                will handle the current event, eventually we will
-                resume all LWPs, and this one will get its breakpoint
-                trap again.
-
-                If we do not do this, then we run the risk that the
-                user will delete or disable the breakpoint, but the
-                thread will have already tripped on it.  */
-
-             /* Save the trap's siginfo in case we need it later.  */
-             save_siginfo (lp);
-
-             save_sigtrap (lp);
-
-             /* Now resume this LWP and get the SIGSTOP event.  */
-             errno = 0;
-             ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0);
-             if (debug_linux_nat)
-               {
-                 fprintf_unfiltered (gdb_stdlog,
-                                     "PTRACE_CONT %s, 0, 0 (%s)\n",
-                                     target_pid_to_str (lp->ptid),
-                                     errno ? safe_strerror (errno) : "OK");
-
-                 fprintf_unfiltered (gdb_stdlog,
-                                     "SWC: Candidate SIGTRAP event in %s\n",
-                                     target_pid_to_str (lp->ptid));
-               }
-             /* Hold this event/waitstatus while we check to see if
-                there are any more (we still want to get that SIGSTOP).  */
-             stop_wait_callback (lp, NULL);
-
-             /* 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));
-               }
+         /* The thread was stopped with a signal other than SIGSTOP.  */
 
-             /* Save the sigtrap event.  */
-             lp->status = status;
-             return 0;
-           }
-         else
-           {
-             /* The thread was stopped with a signal other than
-                SIGSTOP, and didn't accidentally trip a breakpoint.  */
+         /* Save the trap's siginfo in case we need it later.  */
+         save_siginfo (lp);
 
-             if (debug_linux_nat)
-               {
-                 fprintf_unfiltered (gdb_stdlog,
-                                     "SWC: Pending event %s in %s\n",
-                                     status_to_str ((int) status),
-                                     target_pid_to_str (lp->ptid));
-               }
-             /* Now resume this LWP and get the SIGSTOP event.  */
-             errno = 0;
-             ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0);
-             if (debug_linux_nat)
-               fprintf_unfiltered (gdb_stdlog,
-                                   "SWC: PTRACE_CONT %s, 0, 0 (%s)\n",
-                                   target_pid_to_str (lp->ptid),
-                                   errno ? safe_strerror (errno) : "OK");
-
-             /* Hold this event/waitstatus while we check to see if
-                there are any more (we still want to get that SIGSTOP).  */
-             stop_wait_callback (lp, NULL);
-
-             /* 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)
-               {
-                 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 (status));
-               }
-             else
-               lp->status = status;
-             return 0;
-           }
+         save_sigtrap (lp);
+
+         if (debug_linux_nat)
+           fprintf_unfiltered (gdb_stdlog,
+                               "SWC: Pending event %s in %s\n",
+                               status_to_str ((int) status),
+                               target_pid_to_str (lp->ptid));
+
+         /* Save the sigtrap event.  */
+         lp->status = status;
+         gdb_assert (!lp->stopped);
+         gdb_assert (lp->signalled);
+         lp->stopped = 1;
        }
       else
        {
          /* We caught the SIGSTOP that we intended to catch, so
             there's no SIGSTOP pending.  */
+
+         if (debug_linux_nat)
+           fprintf_unfiltered (gdb_stdlog,
+                               "SWC: Delayed SIGSTOP caught for %s.\n",
+                               target_pid_to_str (lp->ptid));
+
          lp->stopped = 1;
+
+         /* Reset SIGNALLED only after the stop_wait_callback call
+            above as it does gdb_assert on SIGNALLED.  */
          lp->signalled = 0;
        }
     }
@@ -3238,7 +3188,7 @@ stop_and_resume_callback (struct lwp_info *lp, void *data)
                fprintf_unfiltered (gdb_stdlog,
                                    "SARC: re-resuming LWP %ld\n",
                                    GET_LWP (lp->ptid));
-             resume_lwp (lp, lp->step);
+             resume_lwp (lp, lp->step, GDB_SIGNAL_0);
            }
          else
            {
@@ -3612,54 +3562,6 @@ retry:
        lp = NULL;
     }
 
-  if (lp && lp->signalled && lp->last_resume_kind != resume_stop)
-    {
-      /* A pending SIGSTOP may interfere with the normal stream of
-         events.  In a typical case where interference is a problem,
-         we have a SIGSTOP signal pending for LWP A while
-         single-stepping it, encounter an event in LWP B, and take the
-         pending SIGSTOP while trying to stop LWP A.  After processing
-         the event in LWP B, LWP A is continued, and we'll never see
-         the SIGTRAP associated with the last time we were
-         single-stepping LWP A.  */
-
-      /* Resume the thread.  It should halt immediately returning the
-         pending SIGSTOP.  */
-      registers_changed ();
-      if (linux_nat_prepare_to_resume != NULL)
-       linux_nat_prepare_to_resume (lp);
-      linux_ops->to_resume (linux_ops, pid_to_ptid (GET_LWP (lp->ptid)),
-                           lp->step, GDB_SIGNAL_0);
-      if (debug_linux_nat)
-       fprintf_unfiltered (gdb_stdlog,
-                           "LLW: %s %s, 0, 0 (expect SIGSTOP)\n",
-                           lp->step ? "PTRACE_SINGLESTEP" : "PTRACE_CONT",
-                           target_pid_to_str (lp->ptid));
-      lp->stopped = 0;
-      gdb_assert (lp->resumed);
-
-      /* Catch the pending SIGSTOP.  */
-      status = lp->status;
-      lp->status = 0;
-
-      stop_wait_callback (lp, NULL);
-
-      /* If the lp->status field isn't empty, we caught another signal
-        while flushing the SIGSTOP.  Return it back to the event
-        queue of the LWP, as we already have an event to handle.  */
-      if (lp->status)
-       {
-         if (debug_linux_nat)
-           fprintf_unfiltered (gdb_stdlog,
-                               "LLW: kill %s, %s\n",
-                               target_pid_to_str (lp->ptid),
-                               status_to_str (lp->status));
-         kill_lwp (GET_LWP (lp->ptid), WSTOPSIG (lp->status));
-       }
-
-      lp->status = status;
-    }
-
   if (!target_can_async_p ())
     {
       /* Causes SIGINT to be passed on to the attached process.  */
This page took 0.042967 seconds and 4 git commands to generate.