[binutils-gdb] init_wait_for_inferior doesn't imply proceed

Pedro Alves via Gdb-cvs <[email protected]>
Newsgroups gmane.comp.gdb.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=fdb1f0881318c83d9db836c9558c33407aca173e

commit fdb1f0881318c83d9db836c9558c33407aca173e
Author: Pedro Alves <[email protected]>
Date:   Wed Feb 19 14:37:39 2025 +0000

    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

Diff:
---
 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<char> 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);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.