* 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.
This commit is contained in:
Pedro Alves 2010-04-30 21:36:45 +00:00
parent 062cbcd610
commit 02fc4de7fc
2 changed files with 57 additions and 14 deletions

View 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.

View 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);
}