This is the mail archive of the gdb-patches@sources.redhat.com 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]

[PATCH] lin-lwp fix


I origionally came up with this patch to fix a intermittent test
failure in gdb.threads/pthreads.exp:

   FAIL: gdb.threads/pthreads.exp: Stopped with a ^C (timeout)
   WARNING: Could not stop child with ^C; skipping rest of tests.

It doesn't fix the problem, but I think it makes the code more robust
and it adds a nice feature that can be used for other smart
optimizations.

Check in.

Mark


Index: ChangeLog

from  Mark Kettenis  <kettenis@gnu.org>
	* lin-lwp.c (stop_wait_callback): Add support for flushing
	signals.  Use that in favour of the old code to get rid of
	superfluous SIGINTs.
	(lin_lwp_wait): Use the new support in stop_wait_callback to
	flush all but one SIGINT.

Index: lin-lwp.c
===================================================================
RCS file: /cvs/src/src/gdb/lin-lwp.c,v
retrieving revision 1.27
diff -u -p -r1.27 lin-lwp.c
--- lin-lwp.c 2001/07/07 10:58:37 1.27
+++ lin-lwp.c 2001/07/12 19:34:59
@@ -595,11 +595,14 @@ stop_callback (struct lwp_info *lp, void
   return 0;
 }
 
-/* Wait until LP is stopped.  */
+/* Wait until LP is stopped.  If DATA is non-null it is interpreted as
+   a pointer to a set of signals to be flushed immediately.  */
 
 static int
 stop_wait_callback (struct lwp_info *lp, void *data)
 {
+  sigset_t *flush_mask = data;
+
   if (! lp->stopped && lp->signalled)
     {
       pid_t pid;
@@ -639,6 +642,13 @@ stop_wait_callback (struct lwp_info *lp,
 
       gdb_assert (WIFSTOPPED (status));
 
+      /* Ignore any signals in FLUSH_MASK.  */
+      if (flush_mask && sigismember (flush_mask, WSTOPSIG (status)))
+	{
+	  ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0);
+	  return stop_wait_callback (lp, flush_mask);
+	}
+
       if (WSTOPSIG (status) != SIGSTOP)
 	{
 	  if (WSTOPSIG (status) == SIGTRAP)
@@ -673,18 +683,6 @@ stop_wait_callback (struct lwp_info *lp,
 	      lp->status = status;
 	      return 0;
 	    }
-	  else if (WSTOPSIG (status) == SIGINT &&
-		   signal_pass_state (SIGINT) == 0)
-	    {
-	      /* Since SIGINT gets forwarded to the entire process group
-		 (in the case where ^C/BREAK is typed at the tty/console),
-		 just ignore all SIGINT events from all lwp's except for
-		 the one that was caught by lin_lwp_wait.  */
-
-	      /* Now resume this LWP and get the SIGSTOP event. */
-	      ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0);
-	      return stop_wait_callback (lp, data);
-	    }
 	  else
 	    {
 	      /* The thread was stopped with a signal other than
@@ -897,6 +895,9 @@ lin_lwp_wait (ptid_t ptid, struct target
   int options = 0;
   int status = 0;
   pid_t pid = PIDGET (ptid);
+  sigset_t flush_mask;
+
+  sigemptyset (&flush_mask);
 
   /* Make sure SIGCHLD is blocked.  */
   if (! sigismember (&blocked_mask, SIGCHLD))
@@ -1113,6 +1114,16 @@ lin_lwp_wait (ptid_t ptid, struct target
 	  status = 0;
 	  goto retry;
 	}
+
+      if (signo == TARGET_SIGNAL_INT
+	  && signal_pass_state (signo) == 0)
+	{
+	  /* If ^C/BREAK is typed at the tty/console, SIGINT gets
+             forwarded to the entire process group, that is, all LWP's
+             will receive it.  Since we only want to report it once,
+             we try to flush it from all LWPs except this one.  */
+	  sigaddset (&flush_mask, SIGINT);
+	}
     }
 
   /* This LWP is stopped now.  */
@@ -1127,7 +1138,7 @@ lin_lwp_wait (ptid_t ptid, struct target
 
   /* ... and wait until all of them have reported back that they're no
      longer running.  */
-  iterate_over_lwps (stop_wait_callback, NULL);
+  iterate_over_lwps (stop_wait_callback, &flush_mask);
 
   /* If we're not waiting for a specific LWP, choose an event LWP from
      among those that have had events.  Giving equal priority to all


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