* linux-low.c (linux_kill_one_lwp, linux_kill)
authorPedro Alves <palves@redhat.com>
Fri, 30 Apr 2010 21:36:45 +0000 (21:36 +0000)
committerPedro Alves <palves@redhat.com>
Fri, 30 Apr 2010 21:36:45 +0000 (21:36 +0000)
(linux_detach_one_lwp): Adjust to send_sigstop interface change.
(send_sigstop): Take an lwp_info as parameter instead.  Queue a
SIGSTOP even if the LWP is stopped.
(send_sigstop_callback): New.
(stop_all_lwps): Use send_sigstop_callback instead.
(linux_resume_one_thread): Adjust.
(proceed_one_lwp): Still proceed an LWP that the client has
requested to stop, if we haven't reported it as stopped yet.  Make
sure that LWPs the client want stopped, have a pending SIGSTOP.

gdb/gdbserver/ChangeLog
gdb/gdbserver/linux-low.c

index bea054be4a9374c2aa5d772df5338acffa067654..4e95c4f32f5d8ff5c2bc9e66fc92464c3fd7816c 100644 (file)
@@ -1,3 +1,16 @@
+2010-04-30  Pedro Alves  <pedro@codesourcery.com>
+
+       * linux-low.c (linux_kill_one_lwp, linux_kill)
+       (linux_detach_one_lwp): Adjust to send_sigstop interface change.
+       (send_sigstop): Take an lwp_info as parameter instead.  Queue a
+       SIGSTOP even if the LWP is stopped.
+       (send_sigstop_callback): New.
+       (stop_all_lwps): Use send_sigstop_callback instead.
+       (linux_resume_one_thread): Adjust.
+       (proceed_one_lwp): Still proceed an LWP that the client has
+       requested to stop, if we haven't reported it as stopped yet.  Make
+       sure that LWPs the client want stopped, have a pending SIGSTOP.
+
 2010-04-26  Doug Evans  <dje@google.com>
 
        * server.c (handle_general_set): Make static.
index 6b7b40f9cd04a43453a8a6346c159ab652c86451..3954d2ddb4fc537c79015a4b3327927aae8cd8c1 100644 (file)
@@ -192,7 +192,7 @@ static int linux_event_pipe[2] = { -1, -1 };
 /* True if we're currently in async mode.  */
 #define target_is_async_p() (linux_event_pipe[0] != -1)
 
-static void send_sigstop (struct inferior_list_entry *entry);
+static void send_sigstop (struct lwp_info *lwp);
 static void wait_for_sigstop (struct inferior_list_entry *entry);
 
 /* Accepts an integer PID; Returns a string representing a file that
@@ -741,7 +741,7 @@ linux_kill_one_lwp (struct inferior_list_entry *entry, void *args)
   /* If we're killing a running inferior, make sure it is stopped
      first, as PTRACE_KILL will not work otherwise.  */
   if (!lwp->stopped)
-    send_sigstop (&lwp->head);
+    send_sigstop (lwp);
 
   do
     {
@@ -781,7 +781,7 @@ linux_kill (int pid)
   /* If we're killing a running inferior, make sure it is stopped
      first, as PTRACE_KILL will not work otherwise.  */
   if (!lwp->stopped)
-    send_sigstop (&lwp->head);
+    send_sigstop (lwp);
 
   do
     {
@@ -814,7 +814,7 @@ linux_detach_one_lwp (struct inferior_list_entry *entry, void *args)
       int lwpid = lwpid_of (lwp);
 
       stopping_threads = 1;
-      send_sigstop (&lwp->head);
+      send_sigstop (lwp);
 
       /* If this detects a new thread through a clone event, the new
         thread is appended to the end of the lwp list, so we'll
@@ -2020,14 +2020,10 @@ kill_lwp (unsigned long lwpid, int signo)
 }
 
 static void
-send_sigstop (struct inferior_list_entry *entry)
+send_sigstop (struct lwp_info *lwp)
 {
-  struct lwp_info *lwp = (struct lwp_info *) entry;
   int pid;
 
-  if (lwp->stopped)
-    return;
-
   pid = lwpid_of (lwp);
 
   /* If we already have a pending stop signal for this process, don't
@@ -2047,6 +2043,17 @@ send_sigstop (struct inferior_list_entry *entry)
   kill_lwp (pid, SIGSTOP);
 }
 
+static void
+send_sigstop_callback (struct inferior_list_entry *entry)
+{
+  struct lwp_info *lwp = (struct lwp_info *) entry;
+
+  if (lwp->stopped)
+    return;
+
+  send_sigstop (lwp);
+}
+
 static void
 mark_lwp_dead (struct lwp_info *lwp, int wstat)
 {
@@ -2159,7 +2166,7 @@ static void
 stop_all_lwps (void)
 {
   stopping_threads = 1;
-  for_each_inferior (&all_lwps, send_sigstop);
+  for_each_inferior (&all_lwps, send_sigstop_callback);
   for_each_inferior (&all_lwps, wait_for_sigstop);
   stopping_threads = 0;
 }
@@ -2661,7 +2668,7 @@ linux_resume_one_thread (struct inferior_list_entry *entry, void *arg)
 
          /* Stop the thread, and wait for the event asynchronously,
             through the event loop.  */
-         send_sigstop (&lwp->head);
+         send_sigstop (lwp);
        }
       else
        {
@@ -2681,7 +2688,7 @@ linux_resume_one_thread (struct inferior_list_entry *entry, void *arg)
             the thread already has a pending status to report, we
             will still report it the next time we wait - see
             status_pending_p_callback.  */
-         send_sigstop (&lwp->head);
+         send_sigstop (lwp);
        }
 
       /* For stop requests, we're done.  */
@@ -2822,10 +2829,12 @@ proceed_one_lwp (struct inferior_list_entry *entry)
 
   thread = get_lwp_thread (lwp);
 
-  if (thread->last_resume_kind == resume_stop)
+  if (thread->last_resume_kind == resume_stop
+      && thread->last_status.kind != TARGET_WAITKIND_IGNORE)
     {
       if (debug_threads)
-       fprintf (stderr, "   client wants LWP %ld stopped\n", lwpid_of (lwp));
+       fprintf (stderr, "   client wants LWP to remain %ld stopped\n",
+                lwpid_of (lwp));
       return;
     }
 
@@ -2844,6 +2853,27 @@ proceed_one_lwp (struct inferior_list_entry *entry)
       return;
     }
 
+  if (thread->last_resume_kind == resume_stop)
+    {
+      /* We haven't reported this LWP as stopped yet (otherwise, the
+        last_status.kind check above would catch it, and we wouldn't
+        reach here.  This LWP may have been momentarily paused by a
+        stop_all_lwps call while handling for example, another LWP's
+        step-over.  In that case, the pending expected SIGSTOP signal
+        that was queued at vCont;t handling time will have already
+        been consumed by wait_for_sigstop, and so we need to requeue
+        another one here.  Note that if the LWP already has a SIGSTOP
+        pending, this is a no-op.  */
+
+      if (debug_threads)
+       fprintf (stderr,
+                "Client wants LWP %ld to stop. "
+                "Making sure it has a SIGSTOP pending\n",
+                lwpid_of (lwp));
+
+      send_sigstop (lwp);
+    }
+
   step = thread->last_resume_kind == resume_step;
   linux_resume_one_lwp (lwp, step, 0, NULL);
 }