Re: [PATCH 2/2] gdb: share some thread proceed related code between CLI and MI

Tom de Vries <[email protected]>
Newsgroups gmane.comp.gdb.patches
Message-ID <[email protected]>
On 8/6/26 10:54 PM, Andrew Burgess wrote:
> I noticed that some code related to proceeding threads could be shared
> between CLI and MI.  This fixes a bug as the CLI code contains a fix
> that the MI code is missing.
> 
> In continue_1 (in infcmd.c) we have a loop that iterates over all
> threads looking for threads that are THREAD_STOPPED and are in an
> inferior that has_execution.  For each thread found we then call:
> 
>    switch_to_thread (&thread);
>    clear_proceed_status (0);
>    proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
> 
> In exec_continue (in mi/mi-main.c) we also have a loop over all
> threads that calls the proceed_thread helper function which skips
> threads that are not THREAD_STOPPED, does some PID related
> filtering (more on this later) and then calls the same three
> functions: switch_to_thread, clear_proceed_status, proceed.
> 
> The PID filtering mentioned above allows proceed_thread to do two
> jobs, if the PID is zero then we proceed all threads.  If PID is
> non-zero then we proceed only the threads in the inferior with that
> PID.
> 
> You might also have spotted that in continue_1 we checked if the
> inferior has execution or not.  This check was added in commit:
> 
>    commit 5b6d1e4fa4fc6827c7b3f0e99ff120dfa14d65d2
>    Date:   Fri Jan 10 20:06:08 2020 +0000
> 
>        Multi-target support
> 
> A matching check was not added into the MI at this point, nor did the
> commit message mention why such a check was not added.  I'm choosing
> to believe that this was an oversight in the 5b6d1e4fa4fc6827 commit.
> And this is the bug I mentioned above.
> 
> If we call `proceed` with a thread that is part of an inferior that
> does not "has_execution" then the thread will be marked running even
> though it will never actually be set running.  See the early return at
> the top of `proceed_resume_thread_checked` and the call to set_state
> in `proceed`.
> 
> I do worry that there might be a bigger set of bugs here if proceed
> can set a thread's state to THREAD_RUNNING, but then never actually
> sets the underlying thread running.  But in this case, just having the
> MI share code with the CLI means that we pick up the fix for this case
> basically for free.
> 
> I propose adding a new global helper function `proceed_one_thread`,
> this will check if the thread is THREAD_STOPPED and is in an inferior
> which has_execution.  If these conditions are met then the three
> functions mentioned above will be called to proceed the thread.
> 
> I will then add a second new function `proceed_all_threads`, this will
> iterate over all threads and call proceed_one_thread.
> 
> We can then use proceed_all_threads from continue_1, replacing the
> existing loop.
> 
> In exec_continue we can move the PID (or rather inferior) check
> earlier, outside the loop.  If we want to resume all threads (the old
> PID is zero path) then we call proceed_all_threads.  If we only want
> to proceed threads with one PID then we loop over threads in the
> matching inferior and call proceed_one_thread on each.
> 
> As the code I am factoring out is all within non_stop only paths I
> have added `gdb_assert (non_stop);` to each of the new helper
> functions, this will prevent these functions accidentally being called
> in the all_stop code path.
> 
> While moving the two `for (...)` loops I have replaced 'auto' with
> 'thread_info' for additional type clarity.
> 
> With the exception of the new has_execution check in the MI path there
> should be no other user visible changes with this commit.  I've added
> a new test which exposes the missing has_execution check issue.

Hi Andrew,

thanks for finding and fixing this.

The functional change is minimal (add one check), and uses a pattern 
already used elsewhere in the code, so LGTM.

Approved-By: Tom de Vries <[email protected]>

FWIW, while reviewing the patch I came to the hypothesis that there are 
really three parts:
- refactoring in infcmd.c
- minimal fix
- refactoring in exec_continue

To verify this, I split off the first two parts, and confirmed that this 
minimal fix (not showing the part removing proceed_thread):
...
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index 8b6da41ffeb..a7e3845d6e3 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -279,7 +265,12 @@ exec_continue (const char *const *argv, int argc)
  	    }

  	  for (auto &thread : all_threads ())
-	    proceed_thread (&thread, pid);
+	    {
+	      if (pid != 0 && thread.ptid.pid () != pid)
+		continue;
+	      proceed_one_thread (thread);
+	    }
+
  	  disable_commit_resumed.reset_and_commit ();
  	}
        else
...
fixes the test-case failure.

I didn't like the escaping in the test-case much, so I wrote a patch 
fixing this (attached).  You could merge before committing, or I can do 
a follow-up commit, as you like.

Thanks,
- Tom
0001-gdb-testsuite-Make-gdb.mi-mi-corefile-and-live.exp-r.patch (text/x-patch, 3.2 KB)
From a88acf26e0346c57fa8275af4d0b26514873aa8a Mon Sep 17 00:00:00 2001
From: Tom de Vries <[email protected]>
Date: Fri, 7 Aug 2026 09:44:12 +0200
Subject: [PATCH] [gdb/testsuite] Make gdb.mi/mi-corefile-and-live.exp regexps
 more readable

---
 gdb/testsuite/gdb.mi/mi-corefile-and-live.exp | 38 ++++++++++---------
 1 file changed, 21 insertions(+), 17 deletions(-)

diff --git a/gdb/testsuite/gdb.mi/mi-corefile-and-live.exp b/gdb/testsuite/gdb.mi/mi-corefile-and-live.exp
index a3a57d3c81a..1a34029d087 100644
--- a/gdb/testsuite/gdb.mi/mi-corefile-and-live.exp
+++ b/gdb/testsuite/gdb.mi/mi-corefile-and-live.exp
@@ -39,8 +39,8 @@ if {$corefile == ""} {
 
 # Start GDB in non-stop and schedule-multiple mode.
 save_vars { GDBFLAGS } {
-    append GDBFLAGS " -ex \"set non-stop on\""
-    append GDBFLAGS " -ex \"set schedule-multiple on\""
+    append GDBFLAGS { -ex "set non-stop on"}
+    append GDBFLAGS { -ex "set schedule-multiple on"}
     mi_clean_restart $::testfile
 }
 
@@ -56,42 +56,46 @@ mi_create_breakpoint "-g i1 foo" \
 
 # Setup inferior 2, this will load the core file.
 mi_gdb_test "-add-inferior" \
-    [multi_line "=thread-group-added,id=\"i2\"" \
-	 "~\"\\\[New inferior 2\\\]\\\\n\"" \
-	 "\~\"Added inferior 2\[^\r\n\]*\\\\n\"" \
-	 "\\^done,inferior=\"\[^\"\]+\"(?:,connection={.*})?" ] \
+    [quotemeta \
+	 [multi_line \
+	      {=thread-group-added,id="i2"} \
+	      {~"[New inferior 2]\n"} \
+	      {~"Added inferior 2@/[^\r\n]*/\n"} \
+	      {^done,inferior="@/[^"]+/"@/(?:,connection={.*})?/}]] \
     "add inferior 2"
 
 # Set the executable for inferior 2.
 mi_gdb_test "-file-exec-and-symbols --thread-group i2 $::binfile" \
-    "\\^done" \
+    [string_to_regexp "^done"] \
     "set executable of inferior 2"
 
 # Load the core file into inferior 2.
 mi_gdb_test \
     "-target-select --thread-group i2 core $::corefile" \
-    [multi_line \
-	 "=thread-group-started,id=\"i2\",.*" \
-	 "=thread-created,id=\"2\",group-id=\"i2\"" \
-	 ".*\\^connected,frame=.*"] \
+    [quotemeta \
+	 [multi_line \
+	      {=thread-group-started,id="i2",@...} \
+	      {=thread-created,id="2",group-id="i2"} \
+	      {@...^connected,frame=@...}]] \
     "load core file in inferior 2"
 
 # Check the core file thread is initially shown as stopped.
-mi_gdb_test "-thread-info 2" ".*,state=\"stopped\".*" \
+mi_gdb_test "-thread-info 2" {.*,state="stopped".*} \
     "core file thread is initially stopped"
 
 # Resume "all" threads.  As the core target doesn't support execution
 # this should not try to set the core target threads running.
 mi_gdb_test "-exec-continue --all" \
-    [multi_line \
-	 "\\^running" \
-	 "\\*running,thread-id=\"1\""] \
+    [string_to_regexp \
+	 [multi_line \
+	      "^running" \
+	      {*running,thread-id="1"}]] \
     "resume all"
 
 # Wait for the non-core target thread to stop.
 mi_expect_stop "breakpoint-hit" \
-    "foo" ".*" ".*" ".*" {"" "disp=\"keep\""} "w1,i2 stop"
+    "foo" ".*" ".*" ".*" {"" {disp="keep"}} "w1,i2 stop"
 
 # Check that the core target thread is still showing as stopped.
-mi_gdb_test "-thread-info 2" ".*,state=\"stopped\".*" \
+mi_gdb_test "-thread-info 2" {.*,state="stopped".*} \
     "core file thread is still stopped"

base-commit: 4df4712cb94f40463daf6a75c71a64eaf84e7901
-- 
2.51.0
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.