2008-10-23  Pedro Alves  <pedro@codesourcery.com>

	* defs.h: Mention ptid_is_pid.
	* inferior.h (ptid_is_pid): Declare.
	* gdbthread.h (struct thread_info) <stop_requested>: New field.
	(set_stop_requested): Declare.
	* infcmd.c (interrupt_target_1): Call set_stop_requested.
	* infrun.c (clear_proceed_status): Clear stop_requested.
	(infrun_thread_stop_requested_callback,
	infrun_thread_stop_requested): New.
	(handle_inferior_event): If a TARGET_SIGNAL_TRAP is reported on a
	thread that had an explicit stop request, pretend we got a
	TARGET_SIGNAL_0.  Always stop if the thread had an explicit stop
	request.
	(print_stop_reason): In the SIGNAL_RECEIVED case, if we're not
	outputting to MI, and we got a TARGET_SIGNAL_0, print "# Stopped",
	instead of mentioning signal 0.
	(ptid_is_pid): New.
	* thread.c (set_stop_requested): New.

	* linux-nat.c (queued_waitpid): Rename to ...
	(queued_waitpid_1): ... this.  Add `peek' argument.  Handle it.
	(queued_waitpid): New, as wrapper to queued_waitpid_1.
	(push_waitpid): Push the SIGTRAP to the local event queue, to the
	kernel's.
	(send_sigint_callback): Delete.
	(linux_nat_stop_lwp): New.
	(linux_nat_stop): Use it.

gdb/doc/
2008-10-23  Pedro Alves  <pedro@codesourcery.com>

	* observer.texi (thread_stop_requested): New.

gdb/testsuite/
2008-10-23  Pedro Alves  <pedro@codesourcery.com>

	* lib/mi-support.exp (mi_expect_interrupt): Expect signal 0
	instead of SIGINT.
This commit is contained in:
Pedro Alves
2008-10-23 23:11:21 +00:00
parent 3c0ed2996e
commit 252fbfc86a
12 changed files with 351 additions and 50 deletions

View File

@ -316,7 +316,6 @@ static void linux_nat_async (void (*callback)
static int linux_nat_async_mask (int mask);
static int kill_lwp (int lwpid, int signo);
static int send_sigint_callback (struct lwp_info *lp, void *data);
static int stop_callback (struct lwp_info *lp, void *data);
/* Captures the result of a successful waitpid call, along with the
@ -333,8 +332,12 @@ struct waitpid_result
in the async SIGCHLD handler. */
static struct waitpid_result *waitpid_queue = NULL;
/* Similarly to `waitpid', but check the local event queue instead of
querying the kernel queue. If PEEK, don't remove the event found
from the queue. */
static int
queued_waitpid (int pid, int *status, int flags)
queued_waitpid_1 (int pid, int *status, int flags, int peek)
{
struct waitpid_result *msg = waitpid_queue, *prev = NULL;
@ -370,12 +373,6 @@ QWPID: linux_nat_async_events_state(%d), linux_nat_num_queued_events(%d)\n",
{
int pid;
if (prev)
prev->next = msg->next;
else
waitpid_queue = msg->next;
msg->next = NULL;
if (status)
*status = msg->status;
pid = msg->pid;
@ -383,7 +380,17 @@ QWPID: linux_nat_async_events_state(%d), linux_nat_num_queued_events(%d)\n",
if (debug_linux_nat_async)
fprintf_unfiltered (gdb_stdlog, "QWPID: pid(%d), status(%x)\n",
pid, msg->status);
xfree (msg);
if (!peek)
{
if (prev)
prev->next = msg->next;
else
waitpid_queue = msg->next;
msg->next = NULL;
xfree (msg);
}
return pid;
}
@ -396,6 +403,14 @@ QWPID: linux_nat_async_events_state(%d), linux_nat_num_queued_events(%d)\n",
return -1;
}
/* Similarly to `waitpid', but check the local event queue. */
static int
queued_waitpid (int pid, int *status, int flags)
{
return queued_waitpid_1 (pid, status, flags, 0);
}
static void
push_waitpid (int pid, int status, int options)
{
@ -2200,11 +2215,11 @@ stop_wait_callback (struct lwp_info *lp, void *data)
/* There was no gdb breakpoint set at pc. Put
the event back in the queue. */
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
"SWC: kill %s, %s\n",
target_pid_to_str (lp->ptid),
status_to_str ((int) status));
kill_lwp (GET_LWP (lp->ptid), WSTOPSIG (status));
fprintf_unfiltered (gdb_stdlog, "\
SWC: leaving SIGTRAP in local queue of %s\n", target_pid_to_str (lp->ptid));
push_waitpid (GET_LWP (lp->ptid),
W_STOPCODE (SIGTRAP),
lp->cloned ? __WCLONE : 0);
}
}
else
@ -4368,15 +4383,76 @@ linux_nat_async (void (*callback) (enum inferior_event_type event_type,
return;
}
/* Stop an LWP, and push a TARGET_SIGNAL_0 stop status if no other
event came out. */
static int
send_sigint_callback (struct lwp_info *lp, void *data)
linux_nat_stop_lwp (struct lwp_info *lwp, void *data)
{
/* Use is_running instead of !lp->stopped, because the lwp may be
stopped due to an internal event, and we want to interrupt it in
that case too. What we want is to check if the thread is stopped
from the point of view of the user. */
if (is_running (lp->ptid))
kill_lwp (GET_LWP (lp->ptid), SIGINT);
ptid_t ptid = * (ptid_t *) data;
if (ptid_equal (lwp->ptid, ptid)
|| ptid_equal (minus_one_ptid, ptid)
|| (ptid_is_pid (ptid)
&& ptid_get_pid (ptid) == ptid_get_pid (lwp->ptid)))
{
if (!lwp->stopped)
{
int pid, status;
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
"LNSL: running -> suspending %s\n",
target_pid_to_str (lwp->ptid));
/* Peek once, to check if we've already waited for this
LWP. */
pid = queued_waitpid_1 (ptid_get_lwp (lwp->ptid), &status,
lwp->cloned ? __WCLONE : 0, 1 /* peek */);
if (pid == -1)
{
ptid_t ptid = lwp->ptid;
stop_callback (lwp, NULL);
stop_wait_callback (lwp, NULL);
/* If the lwp exits while we try to stop it, there's
nothing else to do. */
lwp = find_lwp_pid (ptid);
if (lwp == NULL)
return 0;
pid = queued_waitpid_1 (ptid_get_lwp (lwp->ptid), &status,
lwp->cloned ? __WCLONE : 0,
1 /* peek */);
}
/* If we didn't collect any signal other than SIGSTOP while
stopping the LWP, push a SIGNAL_0 event. In either case,
the event-loop will end up calling target_wait which will
collect these. */
if (pid == -1)
push_waitpid (ptid_get_lwp (lwp->ptid), W_STOPCODE (0),
lwp->cloned ? __WCLONE : 0);
}
else
{
/* Already known to be stopped; do nothing. */
if (debug_linux_nat)
{
if (find_thread_pid (lwp->ptid)->stop_requested)
fprintf_unfiltered (gdb_stdlog, "\
LNSL: already stopped/stop_requested %s\n",
target_pid_to_str (lwp->ptid));
else
fprintf_unfiltered (gdb_stdlog, "\
LNSL: already stopped/no stop_requested yet %s\n",
target_pid_to_str (lwp->ptid));
}
}
}
return 0;
}
@ -4385,13 +4461,9 @@ linux_nat_stop (ptid_t ptid)
{
if (non_stop)
{
if (ptid_equal (ptid, minus_one_ptid))
iterate_over_lwps (send_sigint_callback, &ptid);
else
{
struct lwp_info *lp = find_lwp_pid (ptid);
send_sigint_callback (lp, NULL);
}
linux_nat_async_events (sigchld_sync);
iterate_over_lwps (linux_nat_stop_lwp, &ptid);
target_async (inferior_event_handler, 0);
}
else
linux_ops->to_stop (ptid);