Use observers to report stop events in MI.
authorVladimir Prus <vladimir@codesourcery.com>
Tue, 10 Jun 2008 09:35:09 +0000 (09:35 +0000)
committerVladimir Prus <vladimir@codesourcery.com>
Tue, 10 Jun 2008 09:35:09 +0000 (09:35 +0000)
        * mi/mi-interp.c (mi_on_normal_stop): New.
        (mi_interpreter_init): Register mi_on_normal_stop.
        (mi_interpreter_exec_continuation): Remove.
        (mi_cmd_interpreter_exec): Don't register the above.
        * mi/mi-main.c (captured_mi_execute_command): Don't care
        about sync_execution.
        (mi_execute_async_cli_command): Don't install continuation.  Don't
        print *stopped.
        (mi_exec_async_cli_cmd_continuation): Remove.

gdb/ChangeLog
gdb/infcmd.c
gdb/mi/mi-interp.c
gdb/mi/mi-main.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.mi/mi-break.exp
gdb/testsuite/gdb.mi/mi-syn-frame.exp
gdb/testsuite/gdb.mi/mi2-syn-frame.exp
gdb/testsuite/lib/mi-support.exp

index 4f4e28c2032a90ad5ac2b8c1e0818ac24e8b07b6..f18c6c98c3323a44e66156264433090447c93e45 100644 (file)
@@ -1,3 +1,16 @@
+2008-06-10  Vladimir Prus  <vladimir@codesourcery.com>
+
+       Use observers to report stop events in MI.
+        * mi/mi-interp.c (mi_on_normal_stop): New.
+        (mi_interpreter_init): Register mi_on_normal_stop.
+        (mi_interpreter_exec_continuation): Remove.
+        (mi_cmd_interpreter_exec): Don't register the above.
+        * mi/mi-main.c (captured_mi_execute_command): Don't care
+        about sync_execution.
+        (mi_execute_async_cli_command): Don't install continuation.  Don't
+        print *stopped.
+        (mi_exec_async_cli_cmd_continuation): Remove.
+
 2008-06-10  Vladimir Prus  <vladimir@codesourcery.com>
 
        Suppress normal stop observer when it's problematic.
index a844b7d4c1e386d7aeb07a19216143fa21cdc0bd..01e1ebea6699432bf065f55676758e9764c6479f 100644 (file)
@@ -1383,10 +1383,7 @@ finish_command (char *arg, int from_tty)
   arg1->data.pointer = breakpoint;
   arg2->data.pointer = function;
   add_continuation (finish_command_continuation, arg1);
-
-  /* Do this only if not running asynchronously or if the target
-     cannot do async execution.  Otherwise, complete this command when
-     the target actually stops, in fetch_inferior_event.  */
+  
   discard_cleanups (old_chain);
   if (!target_can_async_p ())
     do_all_continuations (0);
index 8b0d9091c5b3db495eead22c99681675505510bd..583c288a76d5e26a159a2c4ad4bf62cbc0b22d9b 100644 (file)
@@ -65,6 +65,7 @@ static void mi1_command_loop (void);
 
 static void mi_insert_notify_hooks (void);
 static void mi_remove_notify_hooks (void);
+static void mi_on_normal_stop (struct bpstats *bs);
 
 static void mi_new_thread (struct thread_info *t);
 static void mi_thread_exit (struct thread_info *t);
@@ -92,6 +93,7 @@ mi_interpreter_init (int top_level)
     {
       observer_attach_new_thread (mi_new_thread);
       observer_attach_thread_exit (mi_thread_exit);
+      observer_attach_normal_stop (mi_on_normal_stop);
     }
 
   return mi;
@@ -171,26 +173,6 @@ mi_interpreter_prompt_p (void *data)
   return 0;
 }
 
-static void
-mi_interpreter_exec_continuation (struct continuation_arg *arg, int error_p)
-{
-  bpstat_do_actions (&stop_bpstat);
-  /* It's not clear what to do in the case of errror -- should we assume that
-     the target is stopped, or that it still runs?  */
-  if (!target_executing)
-    {
-      fputs_unfiltered ("*stopped", raw_stdout);
-      mi_out_put (uiout, raw_stdout);
-      fputs_unfiltered ("\n", raw_stdout);
-      fputs_unfiltered ("(gdb) \n", raw_stdout);
-      gdb_flush (raw_stdout);
-    }
-  else if (target_can_async_p ())
-    {
-      add_continuation (mi_interpreter_exec_continuation, NULL);
-    }
-}
-
 enum mi_cmd_result
 mi_cmd_interpreter_exec (char *command, char **argv, int argc)
 {
@@ -241,7 +223,6 @@ mi_cmd_interpreter_exec (char *command, char **argv, int argc)
   if (target_can_async_p () && target_executing)
     {
       fputs_unfiltered ("^running\n", raw_stdout);
-      add_continuation (mi_interpreter_exec_continuation, NULL);
     }
 
   if (mi_error_message != NULL)
@@ -325,12 +306,27 @@ static void
 mi_thread_exit (struct thread_info *t)
 {
   struct mi_interp *mi = top_level_interpreter_data ();
-
   target_terminal_ours ();
   fprintf_unfiltered (mi->event_channel, "thread-exited,id=\"%d\"", t->num);
   gdb_flush (mi->event_channel);
 }
 
+static void
+mi_on_normal_stop (struct bpstats *bs)
+{
+  /* Since this can be called when CLI command is executing,
+     using cli interpreter, be sure to use MI uiout for output,
+     not the current one.  */
+  struct ui_out *uiout = interp_ui_out (top_level_interpreter ());
+  struct mi_interp *mi = top_level_interpreter_data ();
+
+  fputs_unfiltered ("*stopped", raw_stdout);
+  mi_out_put (uiout, raw_stdout);
+  mi_out_rewind (uiout);
+  fputs_unfiltered ("\n", raw_stdout);
+  gdb_flush (raw_stdout);
+}
+
 extern initialize_file_ftype _initialize_mi_interp; /* -Wmissing-prototypes */
 
 void
index 4ae509e8e7f7a468cf1fcc98835615e5ce283678..6dc7609ed6cdb36236adf28357f23ad4595a75a3 100644 (file)
@@ -103,10 +103,6 @@ static void mi_execute_cli_command (const char *cmd, int args_p,
                                    const char *args);
 static enum mi_cmd_result mi_execute_async_cli_command (char *cli_command, 
                                                        char **argv, int argc);
-
-static void mi_exec_async_cli_cmd_continuation (struct continuation_arg *arg, 
-                                               int error_p);
-
 static int register_changed_p (int regnum, struct regcache *,
                               struct regcache *);
 static void get_register (int regnum, int format);
@@ -1087,15 +1083,11 @@ captured_mi_execute_command (struct ui_out *uiout, void *data)
              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);
        }
-      else if (sync_execution)
-       {
-         /* Don't print the prompt. We are executing the target in
-            synchronous mode.  */
-         args->action = EXECUTE_COMMAND_SUPPRESS_PROMPT;
-         return;
-       }
       break;
 
     case CLI_COMMAND:
@@ -1311,12 +1303,6 @@ mi_execute_async_cli_command (char *cli_command, char **argv, int argc)
        fputs_unfiltered (current_token, raw_stdout);
       fputs_unfiltered ("^running\n", raw_stdout);
 
-      /* Ideally, we should be intalling continuation only when
-        the target is already running. However, this will break right now,
-        because continuation installed by the 'finish' command must be after
-        the continuation that prints *stopped.  This issue will be
-        fixed soon.  */
-      add_continuation (mi_exec_async_cli_cmd_continuation, NULL);
     }
 
   execute_command ( /*ui */ run, 0 /*from_tty */ );
@@ -1332,30 +1318,13 @@ mi_execute_async_cli_command (char *cli_command, char **argv, int argc)
       /* Do this before doing any printing.  It would appear that some
          print code leaves garbage around in the buffer.  */
       do_cleanups (old_cleanups);
-      /* If the target was doing the operation synchronously we fake
-         the stopped message.  */
-      fputs_unfiltered ("*stopped", raw_stdout);
-      mi_out_put (uiout, raw_stdout);
-      mi_out_rewind (uiout);
       if (do_timings)
        print_diff_now (current_command_ts);
-      fputs_unfiltered ("\n", raw_stdout);
       return MI_CMD_QUIET;
     }    
   return MI_CMD_DONE;
 }
 
-void
-mi_exec_async_cli_cmd_continuation (struct continuation_arg *arg, int error_p)
-{
-  /* Assume 'error' means that target is stopped, too.  */
-  fputs_unfiltered ("*stopped", raw_stdout);
-  mi_out_put (uiout, raw_stdout);
-  fputs_unfiltered ("\n", raw_stdout);
-  fputs_unfiltered ("(gdb) \n", raw_stdout);
-  gdb_flush (raw_stdout);
-}
-
 void
 mi_load_progress (const char *section_name,
                  unsigned long sent_so_far,
index d7673059e8c9812241fc67e2e74910805be71183..d994d1fbc435e64221ff019e4abb79ae75836530 100644 (file)
@@ -1,3 +1,14 @@
+2008-06-10  Vladimir Prus  <vladimir@codesourcery.com>
+
+       * gdb.mi/mi-break.exp (test_ignore_count): Adjust stopped pattern.
+        * gdb.mi/mi-syn-frame.exp: Use mi_expect_stop instead of direct
+        testing of stopped.
+        * gdb.mi/mi2-syn-frame.exp: Likewise.
+        * lib/mi-support.exp (default_mi_gdb_start): Call detect_async.
+        (async, detect_async): New.
+        (mi_expect_stop, mi_continue_to_line): Adjust expectation
+        depending on if we're running in sync or async mode.
+
 2008-06-09  Tom Tromey  <tromey@redhat.com>
 
        * gdb.base/completion.exp: New tests for field name completion
index f2f5b03ae0dd72ab2ce88c77d888709b5887e39a..2798569d463cd27af02a343379103b573fd5c6bd 100644 (file)
@@ -159,7 +159,7 @@ proc test_ignore_count {} {
     mi_run_cmd
 
     gdb_expect {
-        -re ".*func=\"callme\".*args=\\\[\{name=\"i\",value=\"2\"\}\\\].*\r\n$mi_gdb_prompt$" {
+        -re ".*\\*stopped.*func=\"callme\".*args=\\\[\{name=\"i\",value=\"2\"\}\\\].*\r\n($mi_gdb_prompt)?$" {
             pass "run to breakpoint with ignore count"
         }
         -re ".*$mi_gdb_prompt$" {
index 2f2ca026716b19aa48184a5e0dec550e77fbc92e..208678bb83b96481e3d2888843f3b34b6b6c50f6 100644 (file)
@@ -58,9 +58,7 @@ mi_gdb_test "403-exec-continue" \
   "403\\^running" \
   "testing exec continue"
 
-# Presently, the *stopped notification for this case does not include
-# any information.  This can be considered a bug.
-mi_gdb_test "" "\\*stopped" "finished exec continue"
+mi_expect_stop "really-no-reason" "" "" "" "" "" "finished exec continue"
 
 mi_gdb_test "404-stack-list-frames 0 0" \
   "404\\^done,stack=\\\[frame=\{level=\"0\",addr=\"$hex\",func=\"main\",file=\".*mi-syn-frame.c\",fullname=\"${fullname_syntax}${srcfile}\",line=\"$decimal\"\}.*\\\]" \
@@ -88,7 +86,7 @@ mi_gdb_test "407-stack-list-frames" \
 
 mi_gdb_test "408-exec-continue" "408\\^running"
 
-mi_gdb_test "" ".*\\*stopped.*" "finished exec continue"
+mi_expect_stop "really-no-reason" "" "" "" "" "" "finished exec continue"
 
 mi_gdb_test "409-stack-list-frames 0 0" \
   "409\\^done,stack=\\\[frame=\{level=\"0\",addr=\"$hex\",func=\"main\",file=\".*mi-syn-frame.c\",fullname=\"${fullname_syntax}${srcfile}\",line=\"$decimal\"\}.*\\\]" \
index c4474047b54728855641f6c10e1fca6c9d727ec4..b69812fb78fe7467f669eec86227fcf84695b8c4 100644 (file)
@@ -56,15 +56,11 @@ mi_gdb_test "402-stack-list-frames" "402\\^done,stack=\\\[frame=\{level=\"0\",ad
 # Continue back to main()
 #
 
-send_gdb "403-exec-continue\n"
-gdb_expect {
-  -re "403\\^running\[\r\n\]+${my_mi_gdb_prompt}.*\\\*stopped\[\r\n\]+${my_mi_gdb_prompt}$" {
-    pass "403-exec-continue"
-  }
-  timeout {
-    fail "403-exec-continue"
-  }
-}
+mi_gdb_test "403-exec-continue" \
+  "403\\^running" \
+  "testing exec continue"
+
+mi_expect_stop "really-no-reason" "" "" "" "" "" "finished exec continue"
 
 mi_gdb_test "404-stack-list-frames 0 0" \
   "404\\^done,stack=\\\[frame=\{level=\"0\",addr=\"$hex\",func=\"main\",file=\".*mi-syn-frame.c\",fullname=\"${fullname_syntax}${srcfile}\",line=\"$decimal\"\}.*\\\]" \
@@ -89,16 +85,9 @@ mi_gdb_test "407-stack-list-frames" \
   "407\\^done,stack=\\\[frame=\{level=\"0\",addr=\"$hex\",func=\"subroutine\",file=\".*mi-syn-frame.c\",line=\"$decimal\"\},frame=\{level=\"1\",addr=\"$hex\",func=\"handler\",file=\".*mi-syn-frame.c\",line=\"$decimal\"\},frame=\{level=\"2\",addr=\"$hex\",func=\"<signal handler called>\"\},.*frame=\{level=\"$decimal\",addr=\"$hex\",func=\"have_a_very_merry_interrupt\",file=\".*mi-syn-frame.c\",line=\"$decimal\"\},frame=\{level=\"$decimal\",addr=\"$hex\",func=\"<function called from gdb>\"\},frame=\{level=\"$decimal\",addr=\"$hex\",func=\"main\",file=\".*mi-syn-frame.c\",line=\"$decimal\"\}.*\\\]" \
   "list stack frames"
 
+mi_gdb_test "408-exec-continue" "408\\^running"
 
-send_gdb "408-exec-continue\n"
-gdb_expect {
-  -re "408\\^running\[\r\n\]+${my_mi_gdb_prompt}.*\\\*stopped\[\r\n\]+${my_mi_gdb_prompt}$" {
-    pass "408-exec-continue"
-  }
-  timeout {
-    fail "408-exec-continue"
-  }
-}
+mi_expect_stop "really-no-reason" "" "" "" "" "" "finished exec continue"
 
 mi_gdb_test "409-stack-list-frames 0 0" \
   "409\\^done,stack=\\\[frame=\{level=\"0\",addr=\"$hex\",func=\"main\",file=\".*mi-syn-frame.c\",fullname=\"${fullname_syntax}${srcfile}\",line=\"$decimal\"\}.*\\\]" \
index 6a52c88ae8a8c9bb08274b986e6f9efcab9cf35d..23f3f078a78b2e263583a65069720e9a78dd0081 100644 (file)
@@ -227,6 +227,8 @@ proc default_mi_gdb_start { args } {
        }
     }
 
+    detect_async
+
     return 0;
 }
 
@@ -911,6 +913,30 @@ proc mi_step { test } {
   return [mi_step_to {.*} {.*} {.*} {.*} $test]
 }
 
+set async "unknown"
+
+proc detect_async {} {
+    global async
+    global mi_gdb_prompt
+
+    if { $async == "unknown" } {
+        send_gdb "maint show linux-async\n"
+        
+       gdb_expect {
+           -re ".*Controlling the GNU/Linux inferior in asynchronous mode is on...*$mi_gdb_prompt$" {
+                set async 1
+           }
+           -re ".*$mi_gdb_prompt$" {
+                set async 0
+           }
+            timeout {
+                set async 0
+            }
+        }
+    }
+    return $async
+}
+
 # Wait for MI *stopped notification to appear.
 # The REASON, FUNC, ARGS, FILE and LINE are regular expressions
 # to match against whatever is output in *stopped.  ARGS should
@@ -933,6 +959,7 @@ proc mi_expect_stop { reason func args file line extra test } {
     global hex
     global decimal
     global fullname_syntax
+    global async
 
     set after_stopped ""
     set after_reason ""
@@ -944,10 +971,28 @@ proc mi_expect_stop { reason func args file line extra test } {
         set after_stopped [lindex $extra 0]
     }
 
+    if {$async} {
+        set prompt_re ""
+    } else {
+        set prompt_re "$mi_gdb_prompt"
+    }
+
+    if { $reason == "really-no-reason" } {
+        gdb_expect {
+          -re "\\*stopped\r\n$prompt_re$" {
+            pass "$test"
+          }
+          timeout {
+              fail "$test (unknown output after running)"
+          }
+        }
+        return
+    }
+    
     if { $reason == "exited-normally" } {
 
         gdb_expect {
-          -re "\\*stopped,reason=\"exited-normally\"\r\n$mi_gdb_prompt$" {
+          -re "\\*stopped,reason=\"exited-normally\"\r\n$prompt_re$" {
             pass "$test"
           }
           -re ".*$mi_gdb_prompt$" {fail "continue to end (2)"}
@@ -973,17 +1018,17 @@ proc mi_expect_stop { reason func args file line extra test } {
 
     set a $after_reason
 
-    verbose -log "mi_expect_stop: expecting: .*\\*stopped,${r}${a}${bn}thread-id=\"$decimal\",frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\".*$file\",fullname=\"${fullname_syntax}$file\",line=\"$line\"\}$after_stopped\r\n$mi_gdb_prompt$"
+    verbose -log "mi_expect_stop: expecting: .*\\*stopped,${r}${a}${bn}thread-id=\"$decimal\",frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\".*$file\",fullname=\"${fullname_syntax}$file\",line=\"$line\"\}$after_stopped\r\n$prompt_re$"
     gdb_expect {
-       -re ".*\\*stopped,${r}${a}${bn}thread-id=\"$decimal\",frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\".*$file\",fullname=\"${fullname_syntax}$file\",line=\"($line)\"\}$after_stopped\r\n$mi_gdb_prompt$" {
+       -re ".*\\*stopped,${r}${a}${bn}thread-id=\"$decimal\",frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\".*$file\",fullname=\"${fullname_syntax}$file\",line=\"($line)\"\}$after_stopped\r\n$prompt_re$" {
            pass "$test"
             return $expect_out(2,string)
        }
-       -re ".*\\*stopped,${r}${a}${bn}thread-id=\"$decimal\",frame=\{addr=\"$hex\",func=\".*\",args=\[\\\[\{\].*\[\\\]\}\],file=\".*\",fullname=\"${fullname_syntax}.*\",line=\"\[0-9\]*\"\}.*\r\n$mi_gdb_prompt$" {
+       -re ".*\\*stopped,${r}${a}${bn}thread-id=\"$decimal\",frame=\{addr=\"$hex\",func=\".*\",args=\[\\\[\{\].*\[\\\]\}\],file=\".*\",fullname=\"${fullname_syntax}.*\",line=\"\[0-9\]*\"\}.*\r\n$prompt_re$" {
            fail "$test (stopped at wrong place)"
            return -1
        }
-       -re ".*\r\n${mi_gdb_prompt}$" {
+       -re ".*\r\n$mi_gdb_prompt$" {
            fail "$test (unknown output after running)"
            return -1
        }
@@ -1388,9 +1433,16 @@ proc mi_continue_to_line {location test} {
 proc mi_get_stop_line {test} {
 
   global mi_gdb_prompt
+  global async
+
+  if {$async} {
+      set prompt_re ""
+  } else {
+      set prompt_re "$mi_gdb_prompt"
+  }
 
   gdb_expect {
-      -re ".*line=\"(.*)\".*\r\n$mi_gdb_prompt$" {
+      -re ".*line=\"(.*)\".*\r\n$prompt_re$" {
           return $expect_out(1,string)
       }
       -re ".*$mi_gdb_prompt$" {