+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.
/* 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
/* 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
{
/* 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
{
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
}
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
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)
{
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;
}
/* Stop the thread, and wait for the event asynchronously,
through the event loop. */
- send_sigstop (&lwp->head);
+ send_sigstop (lwp);
}
else
{
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. */
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;
}
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);
}