This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFA: non-stop/linux, thread stopping


Hi all,

[ Yet another patch preparing for remote non-stop.  ]

While designing the remote non-stop protocol, and the
"interrupt", "interrupt -a" support, we came up with a new vCont
extension, `vCont;t', or applied to a thread, `vCont;t:TID',
meaning, roughly:

"stop/suspend the target thread TID, however you can and feel like.
If nothing interesting happens to the thread while stopping it, then report
back a TARGET_SIGNAL_0, because I don't care how the thread was
suspended behind the scenes.  You take care of it."

This takes advantage of the fact that TARGET_SIGNAL_0 is defined as:

 src/include/gdb/signal.h:

    /* Used some places (e.g. stop_signal) to record the concept that
       there is no signal.  */
    TARGET_SIGNAL_0 = 0,

When implementing this on gdbserver (ptrace/linux), this effectivelly
translated into stopping an LWP with SIGSTOP, nicelly moving away
from SIGINT, process groups, shared or not-shared signal queues
and the like.

Another propertly of `vCont;t', is that it is defined as doing
nothing to already stopped threads.  This requirement (to not do
anything to stopped threads), implies that threads that were
already stopped due to internal events when an explicit stop
is requested, most notably, threads that are stopped waiting for their
turn in the displaced stepping queue (*), should remain stopped, and
GDB should report that stop as if the target had done so
itself.  That is, GDB should make the stop "public".

There are cases where this property is useful, and following
patches will rely on it.

*) remember we only have one scratch space currently, so
we can only ool-step one thread at a time.

This patch changes native linux non-stop to behave the same, and
adds the necessary glue to the common code.

To make it nicer on the eye, I'm making an output change in
the CLI:

New:

 [Thread 0xf7e306b0 (LWP 26335)] #1 stopped.
 0xffffe410 in __kernel_vsyscall ()

Old:

 Program received signal 0, Signal 0.
 0xffffe410 in __kernel_vsyscall ()

The old output is IMHO, very weird, as a program usually
doesn't stop with a signal 0.  :-)  It also lacked information
of which thread had stopped.

No MI changes are necessary.
*stopped,reason="signal-received",signal-name="0" is still OK.

A frontend can then react accordingly to how the thread was stopped, and treat
signal 0 specialy if it wants to:  Say, if it was a TARGET_SIGNAL_0, then just
perhaps update the thread state icon in a thread tree view, by displaying
a "pause" icon.  If it is was a SIGINT, SIGSEGV or some other signal, then
popup a message box, for example.

How does this all sound?  I'm certain that handle_inferior_event will
need a bit more tweaking here and there to acommodate corner cases, but
I don't expect much.  The base principle is "if the thread had an
explicit request to stop, then when we get a stop event, don't resume
it automatically.".  That's all.

About the code changes themselves:

 - I'm using an observer to make two GDB components comunicate.

      thread.c -> infrun.c

 - ptid_is_pid: new function.  I must have written this function
   5 times already, using 3 different idioms, across several files, but
   I haven't contributed any of those.  Might as well make it to
   common code, where it belongs.  It returns true if a ptid
   represents a process.

 - This was the reason I had added mi_expect_interrupt instead of
   reusing mi_expect_stop.  With this change, since no current target
   will report a SIGINT on a -exec-interrupt, I can just make it only
   recognize signal 0.

All-in-all, tested on x86-pc-linux-gnu.

Does it sound/look sane/OK ?

-- 
Pedro Alves
gdb/
2008-10-16  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-16  Pedro Alves  <pedro@codesourcery.com>

	* observer.texi (thread_stop_requested): New.

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

	* lib/mi-support.exp (mi_expect_interrupt): Expect signal 0
	instead of SIGINT.
	
	

---
 gdb/defs.h                       |    1 
 gdb/doc/observer.texi            |    8 +
 gdb/gdbthread.h                  |   10 ++
 gdb/infcmd.c                     |    1 
 gdb/inferior.h                   |    3 
 gdb/infrun.c                     |  180 ++++++++++++++++++++++++++++++++++-----
 gdb/linux-nat.c                  |  128 +++++++++++++++++++++------
 gdb/testsuite/lib/mi-support.exp |    2 
 gdb/thread.c                     |   25 +++++
 9 files changed, 308 insertions(+), 50 deletions(-)

Index: src/gdb/defs.h
===================================================================
--- src.orig/gdb/defs.h	2008-10-16 03:49:29.000000000 +0100
+++ src/gdb/defs.h	2008-10-16 03:49:30.000000000 +0100
@@ -752,6 +752,7 @@ enum val_prettyprint
       ptid_get_lwp	- Fetch the lwp component of a ptid.
       ptid_get_tid	- Fetch the tid component of a ptid.
       ptid_equal	- Test to see if two ptids are equal.
+      ptid_is_pid	- Test to see if this ptid represents a process id.
 
    Please do NOT access the struct ptid members directly (except, of
    course, in the implementation of the above ptid manipulation
Index: src/gdb/inferior.h
===================================================================
--- src.orig/gdb/inferior.h	2008-10-16 03:49:29.000000000 +0100
+++ src/gdb/inferior.h	2008-10-16 03:49:30.000000000 +0100
@@ -89,6 +89,9 @@ long ptid_get_tid (ptid_t ptid);
 /* Compare two ptids to see if they are equal */
 extern int ptid_equal (ptid_t p1, ptid_t p2);
 
+/* Return true if PTID represents a process id.  */
+extern int ptid_is_pid (ptid_t ptid);
+
 /* Save value of inferior_ptid so that it may be restored by
    a later call to do_cleanups().  Returns the struct cleanup
    pointer needed for later doing the cleanup.  */
Index: src/gdb/gdbthread.h
===================================================================
--- src.orig/gdb/gdbthread.h	2008-10-16 03:49:29.000000000 +0100
+++ src/gdb/gdbthread.h	2008-10-16 03:49:30.000000000 +0100
@@ -168,6 +168,9 @@ struct thread_info
      at.  */
   bpstat stop_bpstat;
 
+  /* True if this thread has been explicitly requested to stop.  */
+  int stop_requested;
+
   /* Private data used by the target vector implementation.  */
   struct private_thread_info *private;
 };
@@ -239,6 +242,13 @@ extern void switch_to_thread (ptid_t pti
    If PIDGET (PTID) is -1, marks all threads.  */
 extern void set_running (ptid_t ptid, int running);
 
+/* Marks or clears thread(s) PTID as having been requested to stop.
+   If PTID is MINUS_ONE_PTID, applies to all threads.  If
+   ptid_is_pid(PTID) is true, applies to all threads of the process
+   pointed at by PTID.  If STOP, then the THREAD_STOP_REQUESTED
+   observer is called with PTID as argument.  */
+extern void set_stop_requested (ptid_t ptid, int stop);
+
 /* NOTE: Since the thread state is not a boolean, most times, you do
    not want to check it with negation.  If you really want to check if
    the thread is stopped,
Index: src/gdb/infcmd.c
===================================================================
--- src.orig/gdb/infcmd.c	2008-10-16 03:49:29.000000000 +0100
+++ src/gdb/infcmd.c	2008-10-16 03:49:30.000000000 +0100
@@ -2169,6 +2169,7 @@ interrupt_target_1 (int all_threads)
   else
     ptid = inferior_ptid;
   target_stop (ptid);
+  set_stop_requested (ptid, 1);
 }
 
 /* Stop the execution of the target while running in async mode, in
Index: src/gdb/infrun.c
===================================================================
--- src.orig/gdb/infrun.c	2008-10-16 03:49:29.000000000 +0100
+++ src/gdb/infrun.c	2008-10-16 03:53:24.000000000 +0100
@@ -1147,6 +1147,7 @@ clear_proceed_status (void)
       tp->step_range_end = 0;
       tp->step_frame_id = null_frame_id;
       tp->step_over_calls = STEP_OVER_UNDEBUGGABLE;
+      tp->stop_requested = 0;
 
       tp->stop_step = 0;
 
@@ -1519,6 +1520,103 @@ static void keep_going (struct execution
 static void print_stop_reason (enum inferior_stop_reason stop_reason,
 			       int stop_info);
 
+/* Callback for iterate over threads.  If the thread is stopped, but
+   the user/frontend doesn't know about that yet, go through
+   normal_stop, as if the thread had just stopped now.  ARG points at
+   a ptid.  If PTID is MINUS_ONE_PTID, applies to all threads.  If
+   ptid_is_pid(PTID) is true, applies to all threads of the process
+   pointed at by PTID.  Otherwise, apply only to the thread pointed by
+   PTID.  */
+
+static int
+infrun_thread_stop_requested_callback (struct thread_info *info, void *arg)
+{
+  ptid_t ptid = * (ptid_t *) arg;
+
+  /* If PTID represents a process, then this applies to all its
+     threads.  If PTID is MINUS_ONE_PTID, then apply to all threads.
+     If */
+  if ((ptid_equal (info->ptid, ptid)
+       || ptid_equal (minus_one_ptid, ptid)
+       || (ptid_is_pid (ptid)
+	   && ptid_get_pid (ptid) == ptid_get_pid (info->ptid)))
+      && is_running (info->ptid)
+      && !is_executing (info->ptid))
+    {
+      struct cleanup *old_chain;
+      struct execution_control_state ecss;
+      struct execution_control_state *ecs = &ecss;
+
+      memset (ecs, 0, sizeof (*ecs));
+
+      old_chain = make_cleanup_restore_current_thread ();
+
+      switch_to_thread (info->ptid);
+
+      /* Go through handle_inferior_event/normal_stop, so we always
+	 have consistent output as if the stop event had been
+	 reported.  */
+      ecs->ptid = info->ptid;
+      ecs->event_thread = find_thread_pid (info->ptid);
+      ecs->ws.kind = TARGET_WAITKIND_STOPPED;
+      ecs->ws.value.sig = TARGET_SIGNAL_0;
+
+      handle_inferior_event (ecs);
+
+      if (!ecs->wait_some_more)
+	{
+	  struct thread_info *tp;
+
+	  normal_stop ();
+
+	  /* Finish off the continuations.  The continations
+	     themselves are responsible for realising the thread
+	     didn't finish what it was supposed to do.  */
+	  tp = inferior_thread ();
+	  do_all_intermediate_continuations_thread (tp);
+	  do_all_continuations_thread (tp);
+	}
+
+      do_cleanups (old_chain);
+    }
+
+  return 0;
+}
+
+/* This function is attached as a "thread_stop_requested" observer.
+   Cleanup local state that assumed the PTID was to be resumed, and
+   report the stop to the frontend.  */
+
+void
+infrun_thread_stop_requested (ptid_t ptid)
+{
+  struct displaced_step_request *it, *next, *prev = NULL;
+
+  /* PTID was requested to stop.  Remove it from the displaced
+     stepping queue, so we don't try to resume it automatically.  */
+  for (it = displaced_step_request_queue; it; it = next)
+    {
+      next = it->next;
+
+      if (ptid_equal (it->ptid, ptid)
+	  || ptid_equal (minus_one_ptid, ptid)
+	  || (ptid_is_pid (ptid)
+	      && ptid_get_pid (ptid) == ptid_get_pid (it->ptid)))
+	{
+	  if (displaced_step_request_queue == it)
+	    displaced_step_request_queue = it->next;
+	  else
+	    prev->next = it->next;
+
+	  xfree (it);
+	}
+      else
+	prev = it;
+    }
+
+  iterate_over_threads (infrun_thread_stop_requested_callback, &ptid);
+}
+
 /* Callback for iterate_over_threads.  */
 
 static int
@@ -2234,11 +2332,21 @@ targets should add new threads to the th
       return;
     }
 
-  /* Do we need to clean up the state of a thread that has completed a
-     displaced single-step?  (Doing so usually affects the PC, so do
-     it here, before we set stop_pc.)  */
   if (ecs->ws.kind == TARGET_WAITKIND_STOPPED)
-    displaced_step_fixup (ecs->ptid, ecs->event_thread->stop_signal);
+    {
+      /* Do we need to clean up the state of a thread that has
+	 completed a displaced single-step?  (Doing so usually affects
+	 the PC, so do it here, before we set stop_pc.)  */
+      displaced_step_fixup (ecs->ptid, ecs->event_thread->stop_signal);
+
+      /* If we either finished a single-step or hit a breakpoint, but
+	 the user wanted this thread to be stopped, pretend we got a
+	 SIG0 (generic unsignaled stop).  */
+
+      if (ecs->event_thread->stop_requested
+	  && ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP)
+	ecs->event_thread->stop_signal = TARGET_SIGNAL_0;
+    }
 
   stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
 
@@ -2734,9 +2842,11 @@ process_event_stop_test:
 	  target_terminal_ours_for_output ();
 	  print_stop_reason (SIGNAL_RECEIVED, ecs->event_thread->stop_signal);
 	}
-      /* Always stop on signals if we're just gaining control of the
-	 program.  */
+      /* Always stop on signals if we're either just gaining control
+	 of the program, or the user explicitly requested this thread
+	 to remain stopped.  */
       if (stop_soon != NO_STOP_QUIETLY
+	  || ecs->event_thread->stop_requested
 	  || signal_stop_state (ecs->event_thread->stop_signal))
 	{
 	  stop_stepping (ecs);
@@ -3750,22 +3860,36 @@ print_stop_reason (enum inferior_stop_re
       return_child_result_value = stop_info;
       break;
     case SIGNAL_RECEIVED:
-      /* Signal received. The signal table tells us to print about
-         it. */
+      /* Signal received.  The signal table tells us to print about
+	 it. */
       annotate_signal ();
-      ui_out_text (uiout, "\nProgram received signal ");
-      annotate_signal_name ();
-      if (ui_out_is_mi_like_p (uiout))
-	ui_out_field_string
-	  (uiout, "reason", async_reason_lookup (EXEC_ASYNC_SIGNAL_RECEIVED));
-      ui_out_field_string (uiout, "signal-name",
-			   target_signal_to_name (stop_info));
-      annotate_signal_name_end ();
-      ui_out_text (uiout, ", ");
-      annotate_signal_string ();
-      ui_out_field_string (uiout, "signal-meaning",
-			   target_signal_to_string (stop_info));
-      annotate_signal_string_end ();
+
+      if (0 && (stop_info == TARGET_SIGNAL_0 && !ui_out_is_mi_like_p (uiout)))
+	{
+	  struct thread_info *t = inferior_thread ();
+
+	  ui_out_text (uiout, "\n[");
+	  ui_out_field_string (uiout, "thread-name",
+			       target_pid_to_str (t->ptid));
+	  ui_out_field_fmt (uiout, "thread-id", "] #%d", t->num);
+	  ui_out_text (uiout, " stopped");
+	}
+      else
+	{
+	  ui_out_text (uiout, "\nProgram received signal ");
+	  annotate_signal_name ();
+	  if (ui_out_is_mi_like_p (uiout))
+	    ui_out_field_string
+	      (uiout, "reason", async_reason_lookup (EXEC_ASYNC_SIGNAL_RECEIVED));
+	  ui_out_field_string (uiout, "signal-name",
+			       target_signal_to_name (stop_info));
+	  annotate_signal_name_end ();
+	  ui_out_text (uiout, ", ");
+	  annotate_signal_string ();
+	  ui_out_field_string (uiout, "signal-meaning",
+			       target_signal_to_string (stop_info));
+	  annotate_signal_string_end ();
+	}
       ui_out_text (uiout, ".\n");
       break;
     default:
@@ -4672,6 +4796,19 @@ ptid_equal (ptid_t ptid1, ptid_t ptid2)
 	  && ptid1.tid == ptid2.tid);
 }
 
+/* Returns true if PTID represents a process.  */
+
+int
+ptid_is_pid (ptid_t ptid)
+{
+  if (ptid_equal (minus_one_ptid, ptid))
+    return 0;
+  if (ptid_equal (null_ptid, ptid))
+    return 0;
+
+  return (ptid_get_lwp (ptid) == 0 && ptid_get_tid (ptid) == 0);
+}
+
 /* restore_inferior_ptid() will be used by the cleanup machinery
    to restore the inferior_ptid value saved in a call to
    save_inferior_ptid().  */
@@ -4932,4 +5069,5 @@ breakpoints, even if such is supported b
   displaced_step_ptid = null_ptid;
 
   observer_attach_thread_ptid_changed (infrun_thread_ptid_changed);
+  observer_attach_thread_stop_requested (infrun_thread_stop_requested);
 }
Index: src/gdb/thread.c
===================================================================
--- src.orig/gdb/thread.c	2008-10-16 03:49:29.000000000 +0100
+++ src/gdb/thread.c	2008-10-16 03:49:30.000000000 +0100
@@ -606,6 +606,31 @@ set_executing (ptid_t ptid, int executin
     }
 }
 
+void
+set_stop_requested (ptid_t ptid, int stop)
+{
+  struct thread_info *tp;
+  int all = ptid_equal (ptid, minus_one_ptid);
+
+  if (all || ptid_is_pid (ptid))
+    {
+      for (tp = thread_list; tp; tp = tp->next)
+	if (all || ptid_get_pid (tp->ptid) == ptid_get_pid (ptid))
+	  tp->stop_requested = stop;
+    }
+  else
+    {
+      tp = find_thread_pid (ptid);
+      gdb_assert (tp);
+      tp->stop_requested = stop;
+    }
+
+  /* Call the stop requested observer so other components of GDB can
+     react to this request.  */
+  if (stop)
+    observer_notify_thread_stop_requested (ptid);
+}
+
 /* Prints the list of threads and their details on UIOUT.
    This is a version of 'info_thread_command' suitable for
    use from MI.  
Index: src/gdb/linux-nat.c
===================================================================
--- src.orig/gdb/linux-nat.c	2008-10-16 03:49:29.000000000 +0100
+++ src/gdb/linux-nat.c	2008-10-16 03:49:30.000000000 +0100
@@ -316,7 +316,6 @@ static void linux_nat_async (void (*call
 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),
     {
       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),
       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),
   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,
 		      /* 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 
   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);
Index: src/gdb/doc/observer.texi
===================================================================
--- src.orig/gdb/doc/observer.texi	2008-10-16 03:49:29.000000000 +0100
+++ src/gdb/doc/observer.texi	2008-10-16 03:49:30.000000000 +0100
@@ -135,6 +135,14 @@ The thread specified by @var{t} has been
 The thread specified by @var{t} has exited.
 @end deftypefun
 
+@deftypefun void thread_stop_requested (ptid_t @var{ptid})
+An explicit stop request was issued to @var{ptid}.  If @var{ptid}
+equals @var{minus_one_ptid}, the request applied to all threads.  If
+@code{ptid_is_pid(ptid)} returns true, the request applied to all
+threads of the process pointed at by @var{ptid}.  Otherwise, the
+request applied to the single thread pointed at by @var{ptid}.
+@end deftypefun
+
 @deftypefun void target_resumed (ptid_t @var{ptid})
 The target was resumed.  The @var{ptid} parameter specifies which
 thread was resume, and may be RESUME_ALL if all threads are resumed.
Index: src/gdb/testsuite/lib/mi-support.exp
===================================================================
--- src.orig/gdb/testsuite/lib/mi-support.exp	2008-10-16 03:49:29.000000000 +0100
+++ src/gdb/testsuite/lib/mi-support.exp	2008-10-16 03:49:30.000000000 +0100
@@ -1050,7 +1050,7 @@ proc mi_expect_interrupt { test } {
 	set prompt_re "$mi_gdb_prompt$"
     }
 
-    set r "reason=\"signal-received\",signal-name=\"SIGINT\",signal-meaning=\"Interrupt\""
+    set r "reason=\"signal-received\",signal-name=\"0\",signal-meaning=\"Signal 0\""
 
     set any "\[^\n\]*"
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]