This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [RFA] Use observers to report stop events.
- From: Vladimir Prus <vladimir at codesourcery dot com>
- To: Daniel Jacobowitz <drow at false dot org>
- Cc: Joel Brobecker <brobecker at adacore dot com>, gdb-patches at sources dot redhat dot com
- Date: Tue, 10 Jun 2008 13:36:23 +0400
- Subject: Re: [RFA] Use observers to report stop events.
- References: <200804112145.58456.vladimir@codesourcery.com> <200805041225.54416.vladimir@codesourcery.com> <20080605154111.GA29085@caradoc.them.org>
On Thursday 05 June 2008 19:41:11 Daniel Jacobowitz wrote:
> On Sun, May 04, 2008 at 12:25:54PM +0400, Vladimir Prus wrote:
> > Are those two new patches, together with the previously posted one
> > (changing stop_observer not to always fire) OK?
>
> For this patch, if an error occurs during proceed (i.e. if the
> cleanup restoring suppress_normal_stop_observer is run), will the
> normal_stop observer ever be called? Is that a problem?
You mean this block:
old_cleanups2 = make_cleanup_restore_integer
(&suppress_normal_stop_observer, 1);
proceed (real_pc, TARGET_SIGNAL_0, 0);
do_cleanups (old_cleanups2);
If proceed throws, before calling normal_stop, we'll get back to event loop,
and run cleanup. We won't call the observer. It's an issue if we've printed
"*running" and thrown after after. However, it's the issue we have now, as
well -- we print ^running even before calling proceed, and if something later
throws, we'll never print *stopped. Possible solutions are:
- Require that frontend refresh thread state on ^error
- Emit *stopped if exception is thrown (this requires checking that the
target is actually stopped, if exception is thrown).
> > + If the argument is pointer to allocated memory, then you need to
>
> is a pointer
>
> > struct cleanup *
> > -make_my_cleanup (struct cleanup **pmy_chain, make_cleanup_ftype *function,
> > - void *arg)
> > +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;
> > + cleanup_chain->free_arg = xfree;
> > + return cleanup;
> > +}
>
> Could you use make_my_cleanup2 here to avoid poking around in
> cleanup_chain, please?
Done.
>
> Also, the only thing value is used for is to set *variable. I
> suggest not setting the variable in a function named
> "make_cleanup_restore_integer", which doesn't say anything about
> setting. So I would prefer this:
>
> old_cleanup = make_cleanup_restore_integer (some_var);
> some_var = 0;
Done.
>
> > * infrun.c (finish_command): Don't pass cleanup
> > to continuation.
> > (finish_command_continuation): Don't grab cleanup from
> > the passed data, as we don't use, and cannot, use it anyway.
>
> OK.
Thanks, checked in. Since there were some adjustment, I attach
the final versions of the patches as checked in.
- Volodya
From d354ec6250185a3083636b349acebb89faafe359 Mon Sep 17 00:00:00 2001
From: Vladimir Prus <vladimir@codesourcery.com>
Date: Tue, 29 Apr 2008 21:31:59 +0400
Subject: [RFA] Introduce common cleanup for restoring integers.
To: gdb-patches@sources.redhat.com
X-KMail-Transport: CodeSourcery
X-KMail-Identity: 901867920
* defs.h (make_cleanup_restore_integer): New declaration.
(struct cleanup): New field free_arg.
(make_my_cleanup_2): New.
* utils.c (restore_integer_closure, restore_integer)
(make_cleanup_restore_integer): New.
(make_my_cleanup): Initialize the free_arg field and
renamed to make_my_cleanup_2.
(do_my_cleanups): Call free_arg.
(discard_cleanups): Call free_arg.
* breakpoint.c (restore_always_inserted_mode): Remove.
(update_breakpoints_after_exec): Use make_cleanup_restore_integer.
---
gdb/breakpoint.c | 9 +--------
gdb/defs.h | 14 +++++++++++++-
gdb/utils.c | 42 ++++++++++++++++++++++++++++++++++++++++--
3 files changed, 54 insertions(+), 11 deletions(-)
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 051b753..dd7bf12 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -1435,12 +1435,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)
{
@@ -1456,8 +1450,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);
+ cleanup = make_cleanup_restore_integer (&always_inserted_mode);
always_inserted_mode = 0;
ALL_BREAKPOINTS_SAFE (b, temp)
diff --git a/gdb/defs.h b/gdb/defs.h
index 9069156..ca3fad8 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -230,12 +230,18 @@ enum return_value_convention
Use make_cleanup to add an element to the cleanup chain.
Use do_cleanups to do all cleanup actions back to a given
point in the chain. Use discard_cleanups to remove cleanups
- from the chain back to a given point, not doing them. */
+ from the chain back to a given point, not doing them.
+
+ If the argument is pointer to allocated memory, then you need to
+ to additionally set the 'free_arg' member to a function that will
+ free that memory. This function will be called both when the cleanup
+ is executed and when it's discarded. */
struct cleanup
{
struct cleanup *next;
void (*function) (void *);
+ void (*free_arg) (void *);
void *arg;
};
@@ -339,11 +345,17 @@ 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);
+
extern struct cleanup *make_final_cleanup (make_cleanup_ftype *, void *);
extern struct cleanup *make_my_cleanup (struct cleanup **,
make_cleanup_ftype *, void *);
+extern struct cleanup *make_my_cleanup2 (struct cleanup **,
+ make_cleanup_ftype *, void *,
+ void (*free_arg) (void *));
+
extern struct cleanup *save_cleanups (void);
extern struct cleanup *save_final_cleanups (void);
extern struct cleanup *save_my_cleanups (struct cleanup **);
diff --git a/gdb/utils.c b/gdb/utils.c
index 76ea6b1..cdea5a6 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -277,10 +277,36 @@ 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;
+}
+/* Remember the current value of *VARIABLE and make it restored when the cleanup
+ is run. */
struct cleanup *
-make_my_cleanup (struct cleanup **pmy_chain, make_cleanup_ftype *function,
- void *arg)
+make_cleanup_restore_integer (int *variable)
+{
+ struct restore_integer_closure *c =
+ xmalloc (sizeof (struct restore_integer_closure));
+ c->variable = variable;
+ c->value = *variable;
+
+ return make_my_cleanup2 (&cleanup_chain, restore_integer, (void *)c,
+ xfree);
+}
+
+struct cleanup *
+make_my_cleanup2 (struct cleanup **pmy_chain, make_cleanup_ftype *function,
+ void *arg, void (*free_arg) (void *))
{
struct cleanup *new
= (struct cleanup *) xmalloc (sizeof (struct cleanup));
@@ -288,12 +314,20 @@ make_my_cleanup (struct cleanup **pmy_chain, make_cleanup_ftype *function,
new->next = *pmy_chain;
new->function = function;
+ new->free_arg = free_arg;
new->arg = arg;
*pmy_chain = new;
return old_chain;
}
+struct cleanup *
+make_my_cleanup (struct cleanup **pmy_chain, make_cleanup_ftype *function,
+ void *arg)
+{
+ return make_my_cleanup2 (pmy_chain, function, arg, NULL);
+}
+
/* Discard cleanups and do the actions they describe
until we get back to the point OLD_CHAIN in the cleanup_chain. */
@@ -318,6 +352,8 @@ do_my_cleanups (struct cleanup **pmy_chain,
{
*pmy_chain = ptr->next; /* Do this first incase recursion */
(*ptr->function) (ptr->arg);
+ if (ptr->free_arg)
+ (*ptr->free_arg) (ptr->arg);
xfree (ptr);
}
}
@@ -345,6 +381,8 @@ discard_my_cleanups (struct cleanup **pmy_chain,
while ((ptr = *pmy_chain) != old_chain)
{
*pmy_chain = ptr->next;
+ if (ptr->free_arg)
+ (*ptr->free_arg) (ptr->arg);
xfree (ptr);
}
}
--
1.5.3.5
From 85eda1b65c61be67f9098f001a5f52f70f44c33f Mon Sep 17 00:00:00 2001
From: Vladimir Prus <vladimir@codesourcery.com>
Date: Mon, 9 Jun 2008 21:14:33 +0400
Subject: [RFA] Suppress normal stop observer when it's problematic.
To: gdb-patches@sources.redhat.com
X-KMail-Transport: CodeSourcery
X-KMail-Identity: 901867920
* 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.
---
gdb/infcall.c | 7 ++++++-
gdb/infcmd.c | 10 ++++++++++
gdb/inferior.h | 3 +++
gdb/infrun.c | 3 ++-
4 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/gdb/infcall.c b/gdb/infcall.c
index c065b59..ded3211 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,12 @@ 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);
+ 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 30858f1..a844b7d 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -206,6 +206,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. */
@@ -1294,8 +1297,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);
}
@@ -1362,6 +1370,8 @@ finish_command (char *arg, int from_tty)
}
proceed_to_finish = 1; /* We want stop_registers, please... */
+ make_cleanup_restore_integer (&suppress_normal_stop_observer);
+ 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 1dd152a..7f85507 100644
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -391,6 +391,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 2960acb..1e10ecc 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -3772,7 +3772,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);
--
1.5.3.5
From 36e76ca870e36e406b1c301b28d6e95f514b0974 Mon Sep 17 00:00:00 2001
From: Vladimir Prus <vladimir@codesourcery.com>
Date: Sun, 4 May 2008 12:09:45 +0400
Subject: [RFA] Remove stale code.
To: gdb-patches@sources.redhat.com
X-KMail-Transport: CodeSourcery
X-KMail-Identity: 901867920
* infrun.c (finish_command): Don't pass cleanup
to continuation.
(finish_command_continuation): Don't grab cleanup from
the passed data, as we don't use, and cannot, use it anyway.
---
gdb/infcmd.c | 7 +------
1 files changed, 1 insertions(+), 6 deletions(-)
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 2397c30..30858f1 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -1278,7 +1278,6 @@ finish_command_continuation (struct continuation_arg *arg, int error_p)
breakpoint = (struct breakpoint *) arg->data.pointer;
function = (struct symbol *) arg->next->data.pointer;
- cleanups = (struct cleanup *) arg->next->next->data.pointer;
if (!error_p)
{
@@ -1369,14 +1368,10 @@ finish_command (char *arg, int from_tty)
(struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
arg2 =
(struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
- arg3 =
- (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
arg1->next = arg2;
- arg2->next = arg3;
- arg3->next = NULL;
+ arg2->next = NULL;
arg1->data.pointer = breakpoint;
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
--
1.5.3.5
From 8b8a8557c8b1c34395053105a420fbc252c4fb61 Mon Sep 17 00:00:00 2001
From: Vladimir Prus <vladimir@codesourcery.com>
Date: Mon, 9 Jun 2008 21:18:28 +0400
Subject: [RFA] Use observers to report stop events in MI.
To: gdb-patches@sources.redhat.com
X-KMail-Transport: CodeSourcery
X-KMail-Identity: 901867920
* 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.
---
gdb/infcmd.c | 5 +--
gdb/mi/mi-interp.c | 40 +++++++++-----------
gdb/mi/mi-main.c | 37 +-----------------
gdb/testsuite/gdb.mi/mi-break.exp | 2 +-
gdb/testsuite/gdb.mi/mi-syn-frame.exp | 6 +--
gdb/testsuite/gdb.mi/mi2-syn-frame.exp | 25 +++---------
gdb/testsuite/lib/mi-support.exp | 64 +++++++++++++++++++++++++++++---
7 files changed, 90 insertions(+), 89 deletions(-)
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index a844b7d..01e1ebe 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -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);
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 4ae509e..6dc7609 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -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,31 +1318,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 6a52c88..23f3f07 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$" {
--
1.5.3.5