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 step into inline function, async vs sync, missing prompt


inline-cmds.exp reveals an cli/mi/output difference in sync
vs async modes.  "Stepping" into an inline subroutine in async
mode fails to output the prompt.  diff gdb.log.sync gdb.log.async:

 (gdb) step
 func1 () at ../../../src/gdb/testsuite/gdb.opt/inline-cmds.c:34
 34       bar ();
-(gdb) PASS: gdb.opt/inline-cmds.exp: step into func1
+FAIL: gdb.opt/inline-cmds.exp: step into func1 (timeout)
 finish

We hit the assertion in mi_execute_async_cli_command, since the target
isn't really resumed, so the thread is already stopped when we return
from the execution command.  Normal stepping (not faked stepping into
an inline subroutine) will normally return with the target running
and a continuation installed (in async mode).

The faking was also missing the *running notifications.  That's
what the user_visible_resume_ptid function is for.  We use it's
result to call set_running, which is what ends up triggering the
*running notifications.

Tested x86_64-linux, sync and async modes.  Applied.

Pedro Alves

2011-05-20  Pedro Alves  <pedro@codesourcery.com>

	gdb/
	* infcmd.c: Include "inf-loop.h".
	(step_once): When stepping into an inline subroutine, pretend the
	target has run.  If the target can async, switch the inferior
	event loop to INF_EXEC_COMPLETE.
	* inferior.h (user_visible_resume_ptid): Declare.
	* infrun.c (user_visible_resume_ptid): New function, factored out
	from `resume'.
	(resume): Use it.
	* mi/mi-main.c (mi_execute_async_cli_command): Remove assertion
	that the current thread is running.  Merge async and sync
	branches.

---
 gdb/infcmd.c     |   16 ++++++++++++--
 gdb/inferior.h   |    2 +
 gdb/infrun.c     |   62 +++++++++++++++++++++++++++++++++++--------------------
 gdb/mi/mi-main.c |   15 ++-----------
 4 files changed, 59 insertions(+), 36 deletions(-)

Index: src/gdb/infcmd.c
===================================================================
--- src.orig/gdb/infcmd.c	2011-05-20 17:14:31.000000000 +0100
+++ src/gdb/infcmd.c	2011-05-20 17:23:51.228819002 +0100
@@ -55,6 +55,7 @@
 #include "valprint.h"
 #include "inline-frame.h"
 #include "tracepoint.h"
+#include "inf-loop.h"
 
 /* Functions exported for general use, in inferior.h: */
 
@@ -994,12 +995,23 @@ step_once (int skip_subroutines, int sin
 	  if (!skip_subroutines && !single_inst
 	      && inline_skipped_frames (inferior_ptid))
 	    {
+	      ptid_t resume_ptid;
+
+	      /* Pretend that we've ran.  */
+	      resume_ptid = user_visible_resume_ptid (1);
+	      set_running (resume_ptid, 1);
+
 	      step_into_inline_frame (inferior_ptid);
 	      if (count > 1)
 		step_once (skip_subroutines, single_inst, count - 1, thread);
 	      else
-		/* Pretend that we've stopped.  */
-		normal_stop ();
+		{
+		  /* Pretend that we've stopped.  */
+		  normal_stop ();
+
+		  if (target_can_async_p ())
+		    inferior_event_handler (INF_EXEC_COMPLETE, NULL);
+		}
 	      return;
 	    }
 
Index: src/gdb/mi/mi-main.c
===================================================================
--- src.orig/gdb/mi/mi-main.c	2011-05-20 17:13:54.000000000 +0100
+++ src/gdb/mi/mi-main.c	2011-05-20 17:23:51.228819002 +0100
@@ -2162,18 +2162,9 @@ mi_execute_async_cli_command (char *cli_
 
   execute_command ( /*ui */ run, 0 /*from_tty */ );
 
-  if (target_can_async_p ())
-    {
-      /* If we're not executing, an exception should have been throw.  */
-      gdb_assert (is_running (inferior_ptid));
-      do_cleanups (old_cleanups);
-    }
-  else
-    {
-      /* Do this before doing any printing.  It would appear that some
-         print code leaves garbage around in the buffer.  */
-      do_cleanups (old_cleanups);
-    }
+  /* Do this before doing any printing.  It would appear that some
+     print code leaves garbage around in the buffer.  */
+  do_cleanups (old_cleanups);
 }
 
 void
Index: src/gdb/inferior.h
===================================================================
--- src.orig/gdb/inferior.h	2011-05-20 17:13:57.000000000 +0100
+++ src/gdb/inferior.h	2011-05-20 17:23:51.228819002 +0100
@@ -188,6 +188,8 @@ extern void reopen_exec_file (void);
 
 extern void resume (int, enum target_signal);
 
+extern ptid_t user_visible_resume_ptid (int step);
+
 /* From misc files */
 
 extern void default_print_registers_info (struct gdbarch *gdbarch,
Index: src/gdb/infrun.c
===================================================================
--- src.orig/gdb/infrun.c	2011-05-20 17:13:59.000000000 +0100
+++ src/gdb/infrun.c	2011-05-20 17:23:51.238819003 +0100
@@ -1601,6 +1601,45 @@ maybe_software_singlestep (struct gdbarc
   return hw_step;
 }
 
+/* Return a ptid representing the set of threads that we will proceed,
+   in the perspective of the user/frontend.  We may actually resume
+   fewer threads at first, e.g., if a thread is stopped at a
+   breakpoint that needs stepping-off, but that should be visible to
+   the user/frontend, and neither should the frontend/user be allowed
+   to proceed any of the threads that happen to be stopped at for
+   internal run control handling, if a previous command wanted them
+   resumed.  */
+
+ptid_t
+user_visible_resume_ptid (int step)
+{
+  /* By default, resume all threads of all processes.  */
+  ptid_t resume_ptid = RESUME_ALL;
+
+  /* Maybe resume only all threads of the current process.  */
+  if (!sched_multi && target_supports_multi_process ())
+    {
+      resume_ptid = pid_to_ptid (ptid_get_pid (inferior_ptid));
+    }
+
+  /* Maybe resume a single thread after all.  */
+  if (non_stop)
+    {
+      /* With non-stop mode on, threads are always handled
+	 individually.  */
+      resume_ptid = inferior_ptid;
+    }
+  else if ((scheduler_mode == schedlock_on)
+	   || (scheduler_mode == schedlock_step
+	       && (step || singlestep_breakpoints_inserted_p)))
+    {
+      /* User-settable 'scheduler' mode requires solo thread resume.  */
+      resume_ptid = inferior_ptid;
+    }
+
+  return resume_ptid;
+}
+
 /* Resume the inferior, but allow a QUIT.  This is useful if the user
    wants to interrupt some lengthy single-stepping operation
    (for child processes, the SIGINT goes to the inferior, and so
@@ -1762,15 +1801,7 @@ a command like `return' or `jump' to con
       /* Decide the set of threads to ask the target to resume.  Start
 	 by assuming everything will be resumed, than narrow the set
 	 by applying increasingly restricting conditions.  */
-
-      /* By default, resume all threads of all processes.  */
-      resume_ptid = RESUME_ALL;
-
-      /* Maybe resume only all threads of the current process.  */
-      if (!sched_multi && target_supports_multi_process ())
-	{
-	  resume_ptid = pid_to_ptid (ptid_get_pid (inferior_ptid));
-	}
+      resume_ptid = user_visible_resume_ptid (step);
 
       /* Maybe resume a single thread after all.  */
       if (singlestep_breakpoints_inserted_p
@@ -1804,19 +1835,6 @@ a command like `return' or `jump' to con
 	     breakpoint, not just the one at PC.  */
 	  resume_ptid = inferior_ptid;
 	}
-      else if (non_stop)
-	{
-	  /* With non-stop mode on, threads are always handled
-	     individually.  */
-	  resume_ptid = inferior_ptid;
-	}
-      else if ((scheduler_mode == schedlock_on)
-	       || (scheduler_mode == schedlock_step
-		   && (step || singlestep_breakpoints_inserted_p)))
-	{
-	  /* User-settable 'scheduler' mode requires solo thread resume.  */
-	  resume_ptid = inferior_ptid;
-	}
 
       if (gdbarch_cannot_step_breakpoint (gdbarch))
 	{


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