aboutsummaryrefslogtreecommitdiff
path: root/gdb/mi
diff options
context:
space:
mode:
authorSimon Marchi <simon.marchi@efficios.com>2023-04-21 12:08:42 -0400
committerSimon Marchi <simon.marchi@efficios.com>2023-05-29 10:09:24 -0400
commitf818c32ba4596a60e77b464cb690aea65ed31346 (patch)
treee15154a0735dc0133816311c6d00a216b50da140 /gdb/mi
parent417bfaa9b5cefb52bc87749251cd3dd37f396aba (diff)
downloadgdb-f818c32ba4596a60e77b464cb690aea65ed31346.zip
gdb-f818c32ba4596a60e77b464cb690aea65ed31346.tar.gz
gdb-f818c32ba4596a60e77b464cb690aea65ed31346.tar.bz2
gdb/mi: fix ^running record with multiple MI interpreters
I stumbled on the mi_proceeded and running_result_record_printed globals, which are shared by all MI interpreter instances (it's unlikely that people use multiple MI interpreter instances, but it's possible). After poking at it, I found this bug: 1. Start GDB in MI mode 2. Add a second MI interpreter with the new-ui command 3. Use -exec-run on the second interpreter This is the output I get on the first interpreter: =thread-group-added,id="i1" ~"Reading symbols from a.out...\n" ~"New UI allocated\n" (gdb) =thread-group-started,id="i1",pid="94718" =thread-created,id="1",group-id="i1" ^running *running,thread-id="all" And this is the output I get on the second intepreter: =thread-group-added,id="i1" (gdb) -exec-run =thread-group-started,id="i1",pid="94718" =thread-created,id="1",group-id="i1" *running,thread-id="all" The problem here is that the `^running` reply to the -exec-run command is printed on the wrong UI. It is printed on the first one, it should be printed on the second (the one on which we sent the -exec-run). What happens under the hood is that captured_mi_execute_command, while executing a command for the second intepreter, clears the running_result_record_printed and mi_proceeded globals. mi_about_to_proceed then sets mi_proceeded. Then, mi_on_resume_1 gets called for the first intepreter first. Since the !running_result_record_printed && mi_proceeded condition is true, it prints a ^running, and sets running_result_record_printed. When mi_on_resume_1 gets called for the second interpreter, running_result_record_printed is already set, so ^running is not printed there. It took me a while to understand the relationship between these two variables. I think that in the end, this is what we want to track: 1. When executing an MI command, take note if that command causes a "proceed". This is done in mi_about_to_proceed. 2. In mi_on_resume_1, if the command indeed caused a "proceed", we want to output a ^running record. And we want to remember that we did, because... 3. Back in captured_mi_execute_command, if we did not output a ^running, we want to output a ^done. Moving those two variables to the mi_interp struture appears to fix it. Only for the interpreter doing the -exec-run command does the running_result_record_printed flag get cleared, and therefore only or that one does the ^running record get printed. Add a new test for this, that does pretty much what the reproducer above shows. Without the fix, the test fails because mi_send_resuming_command_raw never sees the ^running record. Change-Id: I63ea30e6cb61a8e1dd5ef03377e6003381a9209b Tested-By: Alexandra Petlanova Hajkova <ahajkova@redhat.com>
Diffstat (limited to 'gdb/mi')
-rw-r--r--gdb/mi/mi-interp.c13
-rw-r--r--gdb/mi/mi-interp.h6
-rw-r--r--gdb/mi/mi-main.c14
-rw-r--r--gdb/mi/mi-main.h3
4 files changed, 19 insertions, 17 deletions
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 47aeabd..d8b49ae 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -677,7 +677,12 @@ mi_about_to_proceed (void)
return;
}
- mi_proceeded = 1;
+ mi_interp *mi = as_mi_interp (top_level_interpreter ());
+
+ if (mi == nullptr)
+ return;
+
+ mi->mi_proceeded = 1;
}
/* When the element is non-zero, no MI notifications will be emitted in
@@ -961,7 +966,7 @@ mi_on_resume_1 (struct mi_interp *mi,
will make it impossible for frontend to know what's going on.
In future (MI3), we'll be outputting "^done" here. */
- if (!running_result_record_printed && mi_proceeded)
+ if (!mi->running_result_record_printed && mi->mi_proceeded)
{
gdb_printf (mi->raw_stdout, "%s^running\n",
current_token ? current_token : "");
@@ -977,9 +982,9 @@ mi_on_resume_1 (struct mi_interp *mi,
for (thread_info *tp : all_non_exited_threads (targ, ptid))
mi_output_running (tp);
- if (!running_result_record_printed && mi_proceeded)
+ if (!mi->running_result_record_printed && mi->mi_proceeded)
{
- running_result_record_printed = 1;
+ mi->running_result_record_printed = 1;
/* This is what gdb used to do historically -- printing prompt
even if it cannot actually accept any input. This will be
surely removed for MI3, and may be removed even earlier. */
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index e07be12..eb81cbe 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -64,6 +64,12 @@ public:
/* MI's CLI builder (wraps OUT). */
struct ui_out *cli_uiout;
+
+ int running_result_record_printed = 1;
+
+ /* Flag indicating that the target has proceeded since the last
+ command was issued. */
+ int mi_proceeded;
};
/* Output the shared object attributes to UIOUT. */
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index 7a8c35c..dc7d717 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -84,12 +84,6 @@ char *current_token;
command including all option, and make it possible. */
static struct mi_parse *current_context;
-int running_result_record_printed = 1;
-
-/* Flag indicating that the target has proceeded since the last
- command was issued. */
-int mi_proceeded;
-
static void mi_cmd_execute (struct mi_parse *parse);
static void mi_execute_async_cli_command (const char *cli_command,
@@ -1818,8 +1812,8 @@ captured_mi_execute_command (struct ui_out *uiout, struct mi_parse *context)
scoped_restore save_token = make_scoped_restore (&current_token,
context->token);
- running_result_record_printed = 0;
- mi_proceeded = 0;
+ mi->running_result_record_printed = 0;
+ mi->mi_proceeded = 0;
switch (context->op)
{
case MI_COMMAND:
@@ -1837,7 +1831,7 @@ captured_mi_execute_command (struct ui_out *uiout, struct mi_parse *context)
to directly use the mi_interp's uiout, since the command
could have reset the interpreter, in which case the current
uiout will most likely crash in the mi_out_* routines. */
- if (!running_result_record_printed)
+ if (!mi->running_result_record_printed)
{
gdb_puts (context->token, mi->raw_stdout);
/* There's no particularly good reason why target-connect results
@@ -1876,7 +1870,7 @@ captured_mi_execute_command (struct ui_out *uiout, struct mi_parse *context)
|| current_interp_named_p (INTERP_MI3)
|| current_interp_named_p (INTERP_MI4))
{
- if (!running_result_record_printed)
+ if (!mi->running_result_record_printed)
{
gdb_puts (context->token, mi->raw_stdout);
gdb_puts ("^done", mi->raw_stdout);
diff --git a/gdb/mi/mi-main.h b/gdb/mi/mi-main.h
index 18687d5..1741f48 100644
--- a/gdb/mi/mi-main.h
+++ b/gdb/mi/mi-main.h
@@ -36,9 +36,6 @@ extern int mi_async_p (void);
extern char *current_token;
-extern int running_result_record_printed;
-extern int mi_proceeded;
-
struct mi_suppress_notification
{
/* Breakpoint notification suppressed? */