Always pass signals to the right thread
[deliverable/binutils-gdb.git] / gdb / infrun.c
index 3c58ff2e7f9029d0492934b0713d6dfddc8648f0..33aa67410d10f5103c9d09689ca8ef76bea0f4da 100644 (file)
@@ -623,7 +623,7 @@ proceed_after_vfork_done (struct thread_info *thread,
                            target_pid_to_str (thread->ptid));
 
       switch_to_thread (thread->ptid);
-      clear_proceed_status ();
+      clear_proceed_status (0);
       proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 0);
     }
 
@@ -1721,15 +1721,6 @@ maybe_software_singlestep (struct gdbarch *gdbarch, CORE_ADDR pc)
   return hw_step;
 }
 
-/* Return a ptid representing the set of threads that we will proceed,
-   in the perspective of the user/frontend.  We may actually resume
-   fewer threads at first, e.g., if a thread is stopped at a
-   breakpoint that needs stepping-off, but that should not be visible
-   to the user/frontend, and neither should the frontend/user be
-   allowed to proceed any of the threads that happen to be stopped for
-   internal run control handling, if a previous command wanted them
-   resumed.  */
-
 ptid_t
 user_visible_resume_ptid (int step)
 {
@@ -1757,6 +1748,12 @@ user_visible_resume_ptid (int step)
       resume_ptid = inferior_ptid;
     }
 
+  /* We may actually resume fewer threads at first, e.g., if a thread
+     is stopped at a breakpoint that needs stepping-off, but that
+     should not be visible to the user/frontend, and neither should
+     the frontend/user be allowed to proceed any of the threads that
+     happen to be stopped for internal run control handling, if a
+     previous command wanted them resumed.  */
   return resume_ptid;
 }
 
@@ -2032,6 +2029,11 @@ clear_proceed_status_thread (struct thread_info *tp)
                        "infrun: clear_proceed_status_thread (%s)\n",
                        target_pid_to_str (tp->ptid));
 
+  /* If this signal should not be seen by program, give it zero.
+     Used for debugging signals.  */
+  if (!signal_pass_state (tp->suspend.stop_signal))
+    tp->suspend.stop_signal = GDB_SIGNAL_0;
+
   tp->control.trap_expected = 0;
   tp->control.step_range_start = 0;
   tp->control.step_range_end = 0;
@@ -2051,26 +2053,24 @@ clear_proceed_status_thread (struct thread_info *tp)
   bpstat_clear (&tp->control.stop_bpstat);
 }
 
-static int
-clear_proceed_status_callback (struct thread_info *tp, void *data)
-{
-  if (is_exited (tp->ptid))
-    return 0;
-
-  clear_proceed_status_thread (tp);
-  return 0;
-}
-
 void
-clear_proceed_status (void)
+clear_proceed_status (int step)
 {
   if (!non_stop)
     {
-      /* In all-stop mode, delete the per-thread status of all
-        threads, even if inferior_ptid is null_ptid, there may be
-        threads on the list.  E.g., we may be launching a new
-        process, while selecting the executable.  */
-      iterate_over_threads (clear_proceed_status_callback, NULL);
+      struct thread_info *tp;
+      ptid_t resume_ptid;
+
+      resume_ptid = user_visible_resume_ptid (step);
+
+      /* In all-stop mode, delete the per-thread status of all threads
+        we're about to resume, implicitly and explicitly.  */
+      ALL_NON_EXITED_THREADS (tp)
+        {
+         if (!ptid_match (tp->ptid, resume_ptid))
+           continue;
+         clear_proceed_status_thread (tp);
+       }
     }
 
   if (!ptid_equal (inferior_ptid, null_ptid))
@@ -2252,6 +2252,9 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step)
       regcache_write_pc (regcache, addr);
     }
 
+  if (siggnal != GDB_SIGNAL_DEFAULT)
+    tp->suspend.stop_signal = siggnal;
+
   /* Record the interpreter that issued the execution command that
      caused this thread to resume.  If the top level interpreter is
      MI/async, and the execution command was a CLI command
@@ -2318,38 +2321,6 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step)
 
   tp->control.trap_expected = tp->stepping_over_breakpoint;
 
-  if (!non_stop)
-    {
-      /* Pass the last stop signal to the thread we're resuming,
-        irrespective of whether the current thread is the thread that
-        got the last event or not.  This was historically GDB's
-        behaviour before keeping a stop_signal per thread.  */
-
-      struct thread_info *last_thread;
-      ptid_t last_ptid;
-      struct target_waitstatus last_status;
-
-      get_last_target_status (&last_ptid, &last_status);
-      if (!ptid_equal (inferior_ptid, last_ptid)
-         && !ptid_equal (last_ptid, null_ptid)
-         && !ptid_equal (last_ptid, minus_one_ptid))
-       {
-         last_thread = find_thread_ptid (last_ptid);
-         if (last_thread)
-           {
-             tp->suspend.stop_signal = last_thread->suspend.stop_signal;
-             last_thread->suspend.stop_signal = GDB_SIGNAL_0;
-           }
-       }
-    }
-
-  if (siggnal != GDB_SIGNAL_DEFAULT)
-    tp->suspend.stop_signal = siggnal;
-  /* If this signal should not be seen by program,
-     give it zero.  Used for debugging signals.  */
-  else if (!signal_program[tp->suspend.stop_signal])
-    tp->suspend.stop_signal = GDB_SIGNAL_0;
-
   annotate_starting ();
 
   /* Make sure that output from GDB appears before output from the
@@ -2443,7 +2414,7 @@ init_wait_for_inferior (void)
 
   breakpoint_init_inferior (inf_starting);
 
-  clear_proceed_status ();
+  clear_proceed_status (0);
 
   target_last_wait_ptid = minus_one_ptid;
 
@@ -5190,6 +5161,10 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
         what keep_going does as well, if we call it.  */
       ecs->event_thread->control.trap_expected = 0;
 
+      /* Likewise, clear the signal if it should not be passed.  */
+      if (!signal_program[ecs->event_thread->suspend.stop_signal])
+       ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
+
       /* If scheduler locking applies even if not stepping, there's no
         need to walk over threads.  Above we've checked whether the
         current thread is stepping.  If some other thread not the
This page took 0.026139 seconds and 4 git commands to generate.