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]

Fix a couple of multiexec races


The attached patch fixes a couple of glitches preventing (upcoming)
'-exec-run --all' from working.

First, consider this code inside linux_nat_wait_1:

	  if (lp
	      && ptid_is_pid (ptid)
	      && ptid_get_pid (lp->ptid) != ptid_get_pid (ptid))
	    {

	      if (debug_linux_nat)
			fprintf (stderr, "LWP %ld got an event %06x, leaving pending.\n",
					 ptid_get_lwp (lp->ptid), status);

              if (WIFSTOPPED (lp->status))
                {
                 if (WSTOPSIG (lp->status) != SIGSTOP)
                   {
                     stop_callback (lp, NULL);

                     /* Resume in order to collect the sigstop.  */
                     ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0);

                     stop_wait_callback (lp, NULL);
                   }

Because lp->status is naturally not NULL when calling stop_callback, and because
stop_callback has:

	 gdb_assert (lp->status == 0);

if we ever enter the inner "if", GDB will crash. Offlist, Pedro suggested the inner if be
just removed.

Second change is to address the issue I have reported earlier. I reproduce the original 
email below.


I have read the comment inside cancel_breakpoints_callback, but I am not sure
I fully understand it. The situation being handled is when GDB expects an
event in thread A, and thread B hits a breakpoint. For all-stop mode, this
makes sense -- after all we don't support reporting more than one event, and
when user examines event in A he might indeed delete a breakpoint. And if he
does not deletes a breakpoint, 'continue' resumes all threads by default,
so we'll hit breakpoint in B again.

But is this reasonable for non-stop. In non-stop, we get can further stop
events while user examines event in A. Further, 'continue' resumes only
the current thread. So, if we don't report event in B, user does not have
any idea it has to be resumed.

What I observe, specifically, is when I use '-exec-run --all' (a local patch),
one inferior is not resumed. Here's the relevant bit of 'debug lin-lwp' output:

        *running,thread-id="2"
        &"linux_nat_wait: [process 4659]\n"
        &"LLW: waitpid 4656 received Trace/breakpoint trap (stopped)\n"
        LWP 4656 got an event 00057f, leaving pending.
        &"LLW: waitpid 4659 received Trace/breakpoint trap (stopped)\n"
        &"LLW: Candidate event Trace/breakpoint trap (stopped) in process 4659.\n"
        &"CB: Push back breakpoint for process 4656\n"

And there's no further mention of this pid in the log; it remains stopped. The
attached patch appears to improve things. Pedro, what do you think?

Note that this patch also comments out the code that tries to stop a thread if
it got != SIGSTOP. As discussed offlist, that code fires assertion inside
stop_callback.

- Volodya

commit 12fb288b309af44de0b6709d80d172be852368ad
Author: Vladimir Prus <vladimir@codesourcery.com>
Date:   Fri Jan 8 17:07:44 2010 +0300

    Fix issues preventing '-exec-run --all' from work.
    
    	* linux-nat.c (linux_nat_wait_1): When getting event in undesired
    	inferior, do not try to resume it and get SIGSTOP. In non-stop, do
    	not try to cancel breakpoints.

diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index bf0a5f1..682949d 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -3419,20 +3419,9 @@ retry:
 
 	      if (WIFSTOPPED (lp->status))
 		{
-		  if (WSTOPSIG (lp->status) != SIGSTOP)
-		    {
-		      stop_callback (lp, NULL);
-
-		      /* Resume in order to collect the sigstop.  */
-		      ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0);
-
-		      stop_wait_callback (lp, NULL);
-		    }
-		  else
-		    {
-		      lp->stopped = 1;
-		      lp->signalled = 0;
-		    }
+		  lp->stopped = 1;
+		  if (WSTOPSIG (lp->status) == SIGSTOP)
+		    lp->signalled = 0;
 		}
 	      else if (WIFEXITED (status) || WIFSIGNALED (status))
 		{
@@ -3621,7 +3610,8 @@ retry:
   /* Now that we've selected our final event LWP, cancel any
      breakpoints in other LWPs that have hit a GDB breakpoint.  See
      the comment in cancel_breakpoints_callback to find out why.  */
-  iterate_over_lwps (minus_one_ptid, cancel_breakpoints_callback, lp);
+  if (!non_stop)
+    iterate_over_lwps (minus_one_ptid, cancel_breakpoints_callback, lp);
 
   if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP)
     {

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