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.
This commit is contained in:
parent
f5871ec07b
commit
f7f9a841a3
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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$" {
|
||||
|
|
|
@ -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\"\}.*\\\]" \
|
||||
|
|
|
@ -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\"\}.*\\\]" \
|
||||
|
|
|
@ -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$" {
|
||||
|
|
Loading…
Reference in New Issue