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]

[MI/RFC] Emit ^running via observer.


This patch fixes an issue in MI code that was present since at least 1999.
We output ^running before even trying to resume the target, not to mention
making sure the target is resumed. So, if resuming fails, we'd get ^running,
followed by ^error, and I don't really know if current frontends will like
it at all.

Now that we have observer for resume, and that observer is called after target
is resumed, we can emit ^running from that observer. The immediate bonus
is that ^running is now emitted for every command that resumes the inferior,
even for CLI commands. Another (unexpected) bonus, is that since now ^running
and *running is output in a single place, we can produce them in consistent order.
Previously, we would output:

    ^running
    (gdb)
    *running,...

in sync mode and:

    ^running
    *running,...
    (gdb)

in async mode, which makes testing for *running a bit hard.

I indend to double-check that we'll never output ^running except
immediately during processing of MI command, but otherwise I think
this is ready to go in. I'll commit in a few days if there are no
objections.

- Volodya

	[gdb]
	* mi/mi-interp.c (mi_cmd_interpreter_exec): Do no print
	^running here.
	(mi_on_resume): Print ^running if not previously output.
	* mi/mi-main.c (running_result_record_printed): New.
	(captured_mi_execute_command): Reset
	running_result_record_printed.  Use running_result_record_printed
	to decide if we should skip ^done.
	(mi_execute_async_cli_command): Don't print ^running here.
	* mi/mi-main.h (current_token, running_result_record_printed):
	Declare.

	[gdb/testsuite]
	* gdb.mi/mi-async.exp: No longer expect ^running followed by
	^done, expect just ^running.
	* gdb.mi/mi-support.exp (mi_run_cmd, mi_send_resuming_command):
	Demand that *running is output.
---
 gdb/mi/mi-interp.c                |   37 ++++++++++++++-----
 gdb/mi/mi-main.c                  |   71 ++++++++++++-------------------------
 gdb/mi/mi-main.h                  |    5 +++
 gdb/testsuite/gdb.mi/mi-async.exp |   12 +++---
 gdb/testsuite/lib/mi-support.exp  |    4 +-
 5 files changed, 63 insertions(+), 66 deletions(-)

diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index e31afc7..e329b8b 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -217,16 +217,6 @@ mi_cmd_interpreter_exec (char *command, char **argv, int argc)
 
   mi_remove_notify_hooks ();
 
-  /* Okay, now let's see if the command set the inferior going...
-     Tricky point - have to do this AFTER resetting the interpreter, since
-     changing the interpreter will clear out all the continuations for
-     that interpreter... */
-
-  if (target_can_async_p () && any_running ())
-    {
-      fputs_unfiltered ("^running\n", raw_stdout);
-    }
-
   if (mi_error_message != NULL)
     error ("%s", mi_error_message);
   do_cleanups (old_chain);
@@ -332,6 +322,21 @@ mi_on_normal_stop (struct bpstats *bs)
 static void
 mi_on_resume (ptid_t ptid)
 {
+  /* To cater for older frontends, emit ^running, but do it only once
+     per each command.  We do it here, since at this point we know
+     that the target was successfully resumed, and in non-async mode,
+     we won't return back to MI interpreter code until the target
+     is done running, so delaying the output of "^running" until then
+     will make it impossible for frontend to know what's going on.
+
+     In future (MI3), we'll be outputting "^done" here.  */
+  if (!running_result_record_printed)
+    {
+      if (current_token)
+	fputs_unfiltered (current_token, raw_stdout);
+      fputs_unfiltered ("^running\n", raw_stdout);
+    }
+
   if (PIDGET (ptid) == -1)
     fprintf_unfiltered (raw_stdout, "*running,thread-id=\"all\"\n");
   else
@@ -340,6 +345,18 @@ mi_on_resume (ptid_t ptid)
       gdb_assert (ti);
       fprintf_unfiltered (raw_stdout, "*running,thread-id=\"%d\"\n", ti->num);
     }
+
+  if (!running_result_record_printed)
+    {
+      running_result_record_printed = 1;
+      /* This is what gdb used to do historically -- printing prompt even if
+	 it cannot actually accept any input.  This will be surely removed
+	 for MI3, and may be removed even earler.  */
+      /* FIXME: review the use of target_is_async_p here -- is that
+	 what we want? */
+      if (!target_is_async_p ())
+	fputs_unfiltered ("(gdb) \n", raw_stdout);
+    }
 }
 
 extern initialize_file_ftype _initialize_mi_interp; /* -Wmissing-prototypes */
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index 09ed6e3..0f7b8ed 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -94,7 +94,8 @@ static struct mi_timestamp *current_command_ts;
 
 static int do_timings = 0;
 
-static char *current_token;
+char *current_token;
+int running_result_record_printed = 1;
 
 extern void _initialize_mi_main (void);
 static enum mi_cmd_result mi_cmd_execute (struct mi_parse *parse);
@@ -1039,9 +1040,9 @@ captured_mi_execute_command (struct ui_out *uiout, void *data)
 
   struct mi_timestamp cmd_finished;
 
+  running_result_record_printed = 0;
   switch (context->op)
     {
-
     case MI_COMMAND:
       /* A MI command was read from the input stream.  */
       if (mi_debug_p)
@@ -1062,32 +1063,29 @@ captured_mi_execute_command (struct ui_out *uiout, void *data)
       if (do_timings)
 	timestamp (&cmd_finished);
 
-      if (!target_can_async_p () || !is_running (inferior_ptid))
-	{
-	  /* Print the result if there were no errors.
+      /* Print the result if there were no errors.
 
-	     Remember that on the way out of executing a command, you have
-	     to directly use the mi_interp's uiout, since the command could 
-	     have reset the interpreter, in which case the current uiout 
-	     will most likely crash in the mi_out_* routines.  */
-	  if (args->rc == MI_CMD_DONE)
-	    {
-	      fputs_unfiltered (context->token, raw_stdout);
-	      fputs_unfiltered ("^done", raw_stdout);
-	      mi_out_put (uiout, raw_stdout);
-	      mi_out_rewind (uiout);
-	      /* Have to check cmd_start, since the command could be
-		 -enable-timings.  */
-	      if (do_timings && context->cmd_start)
-		  print_diff (context->cmd_start, &cmd_finished);
-	      fputs_unfiltered ("\n", raw_stdout);
-	    }
-	  else
+	 Remember that on the way out of executing a command, you have
+	 to directly use the mi_interp's uiout, since the command could 
+	 have reset the interpreter, in which case the current uiout 
+	 will most likely crash in the mi_out_* routines.  */
+      if (args->rc == MI_CMD_DONE && !running_result_record_printed)
+	{
+	  fputs_unfiltered (context->token, raw_stdout);
+	  fputs_unfiltered ("^done", raw_stdout);
+	  mi_out_put (uiout, raw_stdout);
+	  mi_out_rewind (uiout);
+	  /* Have to check cmd_start, since the command could be
+	     -enable-timings.  */
+	  if (do_timings && context->cmd_start)
+	    print_diff (context->cmd_start, &cmd_finished);
+	  fputs_unfiltered ("\n", raw_stdout);
+	}
+      else
 	    /* The command does not want anything to be printed.  In that
 	       case, the command probably should not have written anything
 	       to uiout, but in case it has written something, discard it.  */
-	    mi_out_rewind (uiout);
-	}
+	mi_out_rewind (uiout);
       break;
 
     case CLI_COMMAND:
@@ -1109,7 +1107,7 @@ captured_mi_execute_command (struct ui_out *uiout, void *data)
 	    || current_interp_named_p (INTERP_MI2)
 	    || current_interp_named_p (INTERP_MI3))
 	  {
-	    if (args->rc == MI_CMD_DONE)
+	    if (args->rc == MI_CMD_DONE && !running_result_record_printed)
 	      {
 		fputs_unfiltered (context->token, raw_stdout);
 		fputs_unfiltered ("^done", raw_stdout);
@@ -1318,29 +1316,6 @@ mi_execute_async_cli_command (char *cli_command, char **argv, int argc)
     run = xstrprintf ("%s %s", cli_command, argc ? *argv : "");
   old_cleanups = make_cleanup (xfree, run);  
 
-  if (!target_can_async_p ())
-    {
-      /* NOTE: For synchronous targets asynchronous behavour is faked by
-         printing out the GDB prompt before we even try to execute the
-         command.  */
-      if (current_token)
-	fputs_unfiltered (current_token, raw_stdout);
-      fputs_unfiltered ("^running\n", raw_stdout);
-      fputs_unfiltered ("(gdb) \n", raw_stdout);
-      gdb_flush (raw_stdout);
-    }
-  else
-    {
-      /* FIXME: cagney/1999-11-29: Printing this message before
-         calling execute_command is wrong.  It should only be printed
-         once gdb has confirmed that it really has managed to send a
-         run command to the target.  */
-      if (current_token)
-	fputs_unfiltered (current_token, raw_stdout);
-      fputs_unfiltered ("^running\n", raw_stdout);
-
-    }
-
   execute_command ( /*ui */ run, 0 /*from_tty */ );
 
   if (target_can_async_p ())
diff --git a/gdb/mi/mi-main.h b/gdb/mi/mi-main.h
index 1a2e93c..1aa5da2 100644
--- a/gdb/mi/mi-main.h
+++ b/gdb/mi/mi-main.h
@@ -25,5 +25,10 @@ extern void mi_load_progress (const char *section_name,
 			      unsigned long total_section,
 			      unsigned long total_sent,
 			      unsigned long grand_total);
+
+extern char *current_token;
+
+extern int running_result_record_printed;
+
 #endif
 
diff --git a/gdb/testsuite/gdb.mi/mi-async.exp b/gdb/testsuite/gdb.mi/mi-async.exp
index d2e3b47..a4efabb 100644
--- a/gdb/testsuite/gdb.mi/mi-async.exp
+++ b/gdb/testsuite/gdb.mi/mi-async.exp
@@ -61,9 +61,9 @@ proc linux_async_tests {} {
 
     send_gdb "start\n"
     gdb_expect {
-	-re ".*\\^running\r\n\\^done\r\n$mi_gdb_prompt" {
+	-re ".*\\^running\r\n(\\*running,thread-id=\"\[^\"\]+\"\r\n)$mi_gdb_prompt" {
 	    gdb_expect {
-		-re "\\*stopped,thread-id=\"0|1\",frame=\{addr=\"$hex\",func=\"main\",args=\\\[\\\],file=\".*basics.c\",line=\"$line_main_body\"\}\r\n$mi_gdb_prompt$" {
+		-re "\\*stopped,thread-id=\"0|1\",frame=\{addr=\"$hex\",func=\"main\",args=\\\[\\\],file=\".*basics.c\",line=\"$line_main_body\"\}\r\n" {
 		    pass "Asynchronous response after start command"
 		}
 		-re ".*$mi_gdb_prompt$" {
@@ -82,9 +82,9 @@ proc linux_async_tests {} {
 
     send_gdb "next\n"
     gdb_expect {
-	-re "\\^running\r\n\\^done\r\n$mi_gdb_prompt" {
+	-re ".*\\^running\r\n(\\*running,thread-id=\"\[^\"\]+\"\r\n)$mi_gdb_prompt" {
 	    gdb_expect {
-		-re "\\*stopped,reason=\"end-stepping-range\",thread-id=\"0|1\",frame=\{addr=\"$hex\",func=\"main\",args=\\\[\\\],file=\".*basics.c\",line=\"$line_main_next\"\}\r\n$mi_gdb_prompt$" {
+		-re "\\*stopped,reason=\"end-stepping-range\",thread-id=\"0|1\",frame=\{addr=\"$hex\",func=\"main\",args=\\\[\\\],file=\".*basics.c\",line=\"$line_main_next\"\}\r\n" {
 		    pass "Asynchronous response after next command"
 		}
 		-re ".*$mi_gdb_prompt$" {
@@ -107,9 +107,9 @@ proc linux_async_tests {} {
 
     send_gdb "start\n"
     gdb_expect {
-	-re ".*\\^running\r\n\\^done\r\n$mi_gdb_prompt" {
+	-re ".*\\^running\r\n(\\*running,thread-id=\"\[^\"\]+\"\r\n)$mi_gdb_prompt" {
 	    gdb_expect {
-		-re "\\*stopped,thread-id=\"0|1\",frame=\{addr=\"$hex\",func=\"main\",args=\\\[\\\],file=\".*basics.c\",line=\"$line_main_body\"\}\r\n$mi_gdb_prompt$" {
+		-re "\\*stopped,thread-id=\"0|1\",frame=\{addr=\"$hex\",func=\"main\",args=\\\[\\\],file=\".*basics.c\",line=\"$line_main_body\"\}\r\n" {
 		    pass "Asynchronous response after (re) start"
 		}
 		-re ".*$mi_gdb_prompt$" {
diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp
index 7a821b8..c8a488c 100644
--- a/gdb/testsuite/lib/mi-support.exp
+++ b/gdb/testsuite/lib/mi-support.exp
@@ -802,7 +802,7 @@ proc mi_run_cmd {args} {
 	if [target_info exists gdb,do_reload_on_run] {
 	    send_gdb "220-exec-continue\n";
 	    gdb_expect 60 {
-		-re "220\\^running\[\r\n\]+(\\*running,thread-id=\"\[^\"\]+\"\r\n)?$mi_gdb_prompt$" {}
+		-re "220\\^running\[\r\n\]+\\*running,thread-id=\"\[^\"\]+\"\r\n$mi_gdb_prompt$" {}
 		default {}
 	    }
 	    return;
@@ -1399,7 +1399,7 @@ proc mi_send_resuming_command {command test} {
 
     send_gdb "220-$command\n"
     gdb_expect {
-        -re "220\\^running\r\n(\\*running,thread-id=\"\[^\"\]+\"\r\n)?${mi_gdb_prompt}" {
+        -re "220\\^running\r\n\\*running,thread-id=\"\[^\"\]+\"\r\n${mi_gdb_prompt}" {
         }
         -re ".*${mi_gdb_prompt}" {
             fail "$test (failed to resume)"
-- 
1.5.3.5



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