aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/gdbserver/ChangeLog13
-rw-r--r--gdb/gdbserver/linux-low.c58
2 files changed, 57 insertions, 14 deletions
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index bea054b..4e95c4f 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -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.
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 6b7b40f..3954d2d 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -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
@@ -2048,6 +2044,17 @@ send_sigstop (struct inferior_list_entry *entry)
}
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)
{
/* It's dead, really. */
@@ -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);
}