From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 29150 invoked by alias); 29 Apr 2008 18:11:10 -0000 Received: (qmail 28783 invoked by uid 22791); 29 Apr 2008 18:11:00 -0000 X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.4) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 29 Apr 2008 18:10:43 +0000 Received: (qmail 24436 invoked from network); 29 Apr 2008 18:10:33 -0000 Received: from unknown (HELO localhost) (vladimir@127.0.0.2) by mail.codesourcery.com with ESMTPA; 29 Apr 2008 18:10:33 -0000 From: Vladimir Prus To: Joel Brobecker , gdb-patches@sources.redhat.com Subject: Re: [RFA] Use observers to report stop events. Date: Tue, 29 Apr 2008 18:30:00 -0000 User-Agent: KMail/1.9.6 (enterprise 0.20070907.709405) References: <200804112145.58456.vladimir@codesourcery.com> <20080429031411.GB28505@adacore.com> In-Reply-To: <20080429031411.GB28505@adacore.com> MIME-Version: 1.0 Content-Type: Multipart/Mixed; boundary="Boundary-00=_XS2FI6aOU5zgSe4" Message-Id: <200804292210.31614.vladimir@codesourcery.com> Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2008-04/txt/msg00668.txt.bz2 --Boundary-00=_XS2FI6aOU5zgSe4 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Content-Disposition: inline Content-length: 3394 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 --Boundary-00=_XS2FI6aOU5zgSe4 Content-Type: text/x-diff; charset="iso-8859-1"; name="1.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="1.diff" Content-length: 2840 commit caf21ec5b9503db75f40d58de005d393da9c10af Author: Vladimir Prus 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, --Boundary-00=_XS2FI6aOU5zgSe4 Content-Type: text/x-diff; charset="iso-8859-1"; name="3.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="3.diff" Content-length: 15686 commit 951a6d036d8808086d11496dd46f7eba6f27fb98 Author: Vladimir Prus 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=\"\"\},.*frame=\{level=\"$decimal\",addr=\"$hex\",func=\"have_a_very_merry_interrupt\",file=\".*mi-syn-frame.c\",line=\"$decimal\"\},frame=\{level=\"$decimal\",addr=\"$hex\",func=\"\"\},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$" { --Boundary-00=_XS2FI6aOU5zgSe4 Content-Type: text/x-diff; charset="iso-8859-1"; name="2.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="2.diff" Content-length: 3702 commit 8f767c7ec7a933f9ac597b7f50420962025d6726 Author: Vladimir Prus 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); --Boundary-00=_XS2FI6aOU5zgSe4--