From fdb1f0881318c83d9db836c9558c33407aca173e Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Wed, 19 Feb 2025 14:37:39 +0000 Subject: [PATCH 1/2] init_wait_for_inferior doesn't imply proceed The next patch adds an assertion to clear_proceed_status_thread, making sure that we don't try to proceed a thread that is already running. Turns out that catches attach_command calling init_wait_for_inferior too late, after attaching has already created already-running threads. This patch fixes. However, that alone changes MI output when attaching (as caught by e.g. gdb.rocm/mi-attach.exp). We'd go from: -target-attach 2468587 =thread-group-started,id="i1",pid="2468587" =thread-created,id="1",group-id="i1" ^done to: -target-attach 2443288 =thread-group-started,id="i1",pid="2443288" =thread-created,id="1",group-id="i1" =thread-created,id="2",group-id="i1" ~"[New LWP 2443317 (id 2)]\n" ^running *running,thread-id="2" (gdb) That change would happen because init_wait_for_inferior calls clear_proceed_status, which calls notify_about_to_proceed, where we end up in mi_interp::on_about_to_proceed(), setting the mi_proceeded flag. If that happens before linux_nat_target::attach is called, then the set_running calls inside linux_nat_target::attach result in emiting ^running in MI instead of ^done due to the back-compatibility hack in mi_on_resume_1. Now, init_wait_inferior really does not imply we're about to call proceed. So restore the MI output by adding a new parameter to clear_proceed_status that lets init_wait_inferior tell clear_proceed_status to skip notifying the about_to_proceed observers. I audited all init_wait_inferior calls, and this made sense in all of them. The places do call proceed after init_wait_inferior, already explicitly clear_proceed_status after init_wait_inferior. E.g., run_command_1. Tested on x86_64-linux-gnu, native and gdbserver. Change-Id: I4f5097d68f4694d44e1ae23fea3e9bce45fb078c commit-id:123f9020 --- gdb/infcmd.c | 8 ++++---- gdb/infrun.c | 7 ++++--- gdb/infrun.h | 5 +++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 98b45f884b1..2be2f4376c0 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -2862,6 +2862,10 @@ attach_command (const char *args, int from_tty) this function should probably be moved into target_pre_inferior. */ target_pre_inferior (); + /* Set up execution context to know that we should return from + wait_for_inferior as soon as the target reports a stop. */ + init_wait_for_inferior (); + gdb::unique_xmalloc_ptr stripped = strip_bg_char (args, &async_exec); args = stripped.get (); @@ -2904,10 +2908,6 @@ attach_command (const char *args, int from_tty) finished. */ target_terminal::inferior (); - /* Set up execution context to know that we should return from - wait_for_inferior as soon as the target reports a stop. */ - init_wait_for_inferior (); - inferior->needs_setup = true; if (target_is_non_stop_p ()) diff --git a/gdb/infrun.c b/gdb/infrun.c index 2e53d2a6c30..a6b5db3edd5 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -3123,7 +3123,7 @@ notify_about_to_proceed () } void -clear_proceed_status (int step) +clear_proceed_status (int step, bool about_to_proceed) { /* With scheduler-locking replay, stop replaying other threads in the same process if we're not replaying the selected thread. @@ -3162,7 +3162,8 @@ clear_proceed_status (int step) inferior->control.stop_soon = NO_STOP_QUIETLY; } - notify_about_to_proceed (); + if (about_to_proceed) + notify_about_to_proceed (); } /* Returns true if TP is still stopped at a breakpoint that needs @@ -3851,7 +3852,7 @@ init_wait_for_inferior (void) breakpoint_init_inferior (current_inferior (), inf_starting); - clear_proceed_status (0); + clear_proceed_status (0, false); nullify_last_target_wait_ptid (); diff --git a/gdb/infrun.h b/gdb/infrun.h index 7e2b652e4f1..9eaa5387ef0 100644 --- a/gdb/infrun.h +++ b/gdb/infrun.h @@ -129,8 +129,9 @@ extern void start_remote (int from_tty); /* Clear out all variables saying what to do when inferior is continued or stepped. First do this, then set the ones you want, then call `proceed'. STEP indicates whether we're preparing for a - step/stepi command. */ -extern void clear_proceed_status (int step); + step/stepi command. Set ABOUT_TO_PROCEED to false if we're not + calling `proceeed` yet. */ +extern void clear_proceed_status (int step, bool about_to_proceed = true); extern void proceed (CORE_ADDR, enum gdb_signal); base-commit: 73434094ad8a861fe555045804e943d186ff6879 -- 2.53.0