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]

Re: [RFA] Use observers to report stop events.


On Tuesday 29 April 2008 07:14:11 you wrote:
> Volodya,
> 
> > 	* defs.h (make_cleanup_restore_integer): New declaration.
> > 	* utils.c (restore_integer_closure, restore_integer)
> > 	(make_cleanup_restore_integer): New.
> > 	* breakpoint.c (restore_always_inserted_mode): Remove.
> > 	(update_breakpoints_after_exec): Use make_cleanup_restore_integer.
> > 
> > 	* inferior.h (suppress_normal_stop_observer): New.
> > 	* infcall.c (call_function_by_hand): Disable stop events when
> > 	doing function calls.
> > 	* infmcd.c (suppress_normal_stop_observer): New.
> > 	(finish_command_continuation): Call normal_stop observer
> > 	explicitly.
> > 	(finish_command): Disable stop events inside proceed.
> > 	* infrun.c (normal_stop): Don't call normal stop observer if
> > 	suppressed of if multi-step is in progress.
> > 
> > 	* interps.h (top_level_interpreter): New.
> > 	* interps.c (top_level_interpreter): Rename to
> > 	top_level_interpreter_ptr.
> > 	(top_level_interpreter): New.
> > 
> > 	* 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.
> 
> I tried to have a look at your patch, but I couldn't get into it
> within the short amount of time that I have today. What I did notice
> is that it contains several changes that could be made independent.
> For instance, the make_cleanup_restore_integer/restore_always_inserted_mode
> part could be introduced separately (honestly, this part looks a little
> scary as you will leak memory is someone cancels the cleanup - so far,
> I think the usual practice is to have one make_cleanup_bla_bla_bla
> that specially restores your variable).
> 
> I need to document myself about the "*stopped async output" because
> I didn't quite get the idea of the patch. But if I had known that this
> patch had some MI-logic to it, I'd probably have stayed away from it.
> I seem to find more excitement in other parts of GDB... If no one else
> gets to it, I'll see I can find some time later in the week or next week
> to try again, but it would definitely help to see this patch broken down
> into smaller pieces.

Here are 3 independent bits.

1. Introduce the make_cleanup_restore_integer function. You're right
that it can lead to bad results if one discards this cleanup, but then
one should be careful with discarding cleanups anyway.

2. Modify the normal_stop observer not to fire in some cases. One
case is when doing function call -- we don't announce the stop in CLI
and for similar reason we don't have observer to be called. Also,
for the benefit of next patch, we want the call to observer to
be delayed until we print function return value, if we're doing finish.

3. The MI patch itself. Note that it does not seen an approval -- I can
self-approve it. The point of the patch is to report target stop in
MI immediately when a stop in some thread is detected by gdb. Currently,
MI reports target stop only when it's done doing some command, which is
incompatible with idea that target can stop many times per one MI command.

Thanks,
Volodya





commit caf21ec5b9503db75f40d58de005d393da9c10af
Author: Vladimir Prus <vladimir@codesourcery.com>
Date:   Tue Apr 29 21:31:59 2008 +0400

    Introduce common cleanup for restoring integers.
        	* defs.h (make_cleanup_restore_integer): New declaration.
        	* utils.c (restore_integer_closure, restore_integer)
        	(make_cleanup_restore_integer): New.
        	* breakpoint.c (restore_always_inserted_mode): Remove.
        	(update_breakpoints_after_exec): Use make_cleanup_restore_integer.

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 4180ea1..af92d47 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -1456,12 +1456,6 @@ reattach_breakpoints (int pid)
   return 0;
 }
 
-static void
-restore_always_inserted_mode (void *p)
-{
-  always_inserted_mode = (uintptr_t) p;
-}
-
 void
 update_breakpoints_after_exec (void)
 {
@@ -1477,9 +1471,7 @@ update_breakpoints_after_exec (void)
   /* The binary we used to debug is now gone, and we're updating
      breakpoints for the new binary.  Until we're done, we should not
      try to insert breakpoints.  */
-  cleanup = make_cleanup (restore_always_inserted_mode, 
-			  (void *) (uintptr_t) always_inserted_mode);
-  always_inserted_mode = 0;
+  cleanup = make_cleanup_restore_integer (&always_inserted_mode, 0);
 
   ALL_BREAKPOINTS_SAFE (b, temp)
   {
diff --git a/gdb/defs.h b/gdb/defs.h
index 0fa0e6c..7966967 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -345,6 +345,8 @@ extern struct cleanup *make_cleanup_close (int fd);
 
 extern struct cleanup *make_cleanup_bfd_close (bfd *abfd);
 
+extern struct cleanup *make_cleanup_restore_integer (int *variable, int value);
+
 extern struct cleanup *make_final_cleanup (make_cleanup_ftype *, void *);
 
 extern struct cleanup *make_my_cleanup (struct cleanup **,
diff --git a/gdb/utils.c b/gdb/utils.c
index d9953a0..fa8e455 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -277,6 +277,33 @@ make_cleanup_free_section_addr_info (struct section_addr_info *addrs)
   return make_my_cleanup (&cleanup_chain, do_free_section_addr_info, addrs);
 }
 
+struct restore_integer_closure
+{
+  int *variable;
+  int value;
+};
+
+static void
+restore_integer (void *p)
+{
+  struct restore_integer_closure *closure = p;
+  *(closure->variable) = closure->value;
+  xfree (closure);
+}
+
+/* Assign VALUE to *VARIABLE and arranges for the old value to
+   be restored via cleanup.  */
+struct cleanup *
+make_cleanup_restore_integer (int *variable, int value)
+{
+  struct restore_integer_closure *c =
+    xmalloc (sizeof (struct restore_integer_closure));
+  struct cleanup *cleanup = make_cleanup (restore_integer, (void *) c);
+  c->variable = variable;
+  c->value = *variable;    
+  *variable = value;
+  return cleanup;
+}
 
 struct cleanup *
 make_my_cleanup (struct cleanup **pmy_chain, make_cleanup_ftype *function,
commit 951a6d036d8808086d11496dd46f7eba6f27fb98
Author: Vladimir Prus <vladimir@codesourcery.com>
Date:   Mon Mar 10 17:52:40 2008 +0300

    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.
    
    	[gdb/testsuite]
    	* 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.

diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index a0980c7..37ca2bb 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -1371,10 +1371,7 @@ finish_command (char *arg, int from_tty)
   arg2->data.pointer = function;
   arg3->data.pointer = old_chain;
   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);
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 8b0d909..583c288 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -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
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index 9dce9b0..206b2c9 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -102,10 +102,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);
@@ -1085,15 +1081,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:
@@ -1309,12 +1301,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 */ );
@@ -1330,31 +1316,14 @@ 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,
 		  unsigned long total_section,
diff --git a/gdb/testsuite/gdb.mi/mi-break.exp b/gdb/testsuite/gdb.mi/mi-break.exp
index f2f5b03..2798569 100644
--- a/gdb/testsuite/gdb.mi/mi-break.exp
+++ b/gdb/testsuite/gdb.mi/mi-break.exp
@@ -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$" {
diff --git a/gdb/testsuite/gdb.mi/mi-syn-frame.exp b/gdb/testsuite/gdb.mi/mi-syn-frame.exp
index 2f2ca02..208678b 100644
--- a/gdb/testsuite/gdb.mi/mi-syn-frame.exp
+++ b/gdb/testsuite/gdb.mi/mi-syn-frame.exp
@@ -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\"\}.*\\\]" \
diff --git a/gdb/testsuite/gdb.mi/mi2-syn-frame.exp b/gdb/testsuite/gdb.mi/mi2-syn-frame.exp
index c447404..b69812f 100644
--- a/gdb/testsuite/gdb.mi/mi2-syn-frame.exp
+++ b/gdb/testsuite/gdb.mi/mi2-syn-frame.exp
@@ -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\"\}.*\\\]" \
diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp
index 1f4c3dd..0783936 100644
--- a/gdb/testsuite/lib/mi-support.exp
+++ b/gdb/testsuite/lib/mi-support.exp
@@ -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$" {
commit 8f767c7ec7a933f9ac597b7f50420962025d6726
Author: Vladimir Prus <vladimir@codesourcery.com>
Date:   Tue Apr 29 21:40:51 2008 +0400

    Suppress normal stop observer when it's problematic.
        	* inferior.h (suppress_normal_stop_observer): New.
        	* infcall.c (call_function_by_hand): Disable stop events when
        	doing function calls.
        	* infmcd.c (suppress_normal_stop_observer): New.
        	(finish_command_continuation): Call normal_stop observer
        	explicitly.
        	(finish_command): Disable stop events inside proceed.
        	* infrun.c (normal_stop): Don't call normal stop observer if
        	suppressed of if multi-step is in progress.

diff --git a/gdb/infcall.c b/gdb/infcall.c
index ca4785e..d8257da 100644
--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -706,6 +706,7 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
 
   {
     struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0);
+    struct cleanup *old_cleanups2;
     int saved_async = 0;
 
     /* If all error()s out of proceed ended up calling normal_stop
@@ -718,8 +719,11 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
 
     if (target_can_async_p ())
       saved_async = target_async_mask (0);
-    
+
+    old_cleanups2 = make_cleanup_restore_integer 
+      (&suppress_normal_stop_observer, 1);
     proceed (real_pc, TARGET_SIGNAL_0, 0);
+    do_cleanups (old_cleanups2);
     
     if (saved_async)
       target_async_mask (saved_async);
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 18aa544..a0980c7 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -205,6 +205,9 @@ int step_multi;
    in format described in environ.h.  */
 
 struct gdb_environ *inferior_environ;
+
+/* When set, normal_stop will not call the normal_stop observer.  */
+int suppress_normal_stop_observer = 0;
 
 /* Accessor routines. */
 
@@ -1279,8 +1282,13 @@ finish_command_continuation (struct continuation_arg *arg, int error_p)
 	  if (TYPE_CODE (value_type) != TYPE_CODE_VOID)
 	    print_return_value (SYMBOL_TYPE (function), value_type); 
 	}
+
+      /* We suppress normal call of normal_stop observer and do it here so that
+	 that *stopped notification includes the return value.  */
+      observer_notify_normal_stop (stop_bpstat);
     }
 
+  suppress_normal_stop_observer = 0;
   delete_breakpoint (breakpoint);
 }
 
@@ -1347,6 +1355,7 @@ finish_command (char *arg, int from_tty)
     }
 
   proceed_to_finish = 1;	/* We want stop_registers, please...  */
+  make_cleanup_restore_integer (&suppress_normal_stop_observer, 1);
   proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
 
   arg1 =
diff --git a/gdb/inferior.h b/gdb/inferior.h
index 3aaaa26..630cc52 100644
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -399,6 +399,9 @@ extern int debug_displaced;
 void displaced_step_dump_bytes (struct ui_file *file,
                                 const gdb_byte *buf, size_t len);
 
+
+/* When set, normal_stop will not call the normal_stop observer.  */
+extern int suppress_normal_stop_observer;
 
 /* Possible values for gdbarch_call_dummy_location.  */
 #define ON_STACK 1
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 0e58749..b0ba57c 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -3627,7 +3627,8 @@ Further execution is probably impossible.\n"));
 
 done:
   annotate_stopped ();
-  observer_notify_normal_stop (stop_bpstat);
+  if (!suppress_normal_stop_observer && !step_multi)
+    observer_notify_normal_stop (stop_bpstat);
   /* Delete the breakpoint we stopped at, if it wants to be deleted.
      Delete any breakpoint that is to be deleted at the next stop.  */
   breakpoint_auto_delete (stop_bpstat);

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