Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH 0/3] Option to show stopped threads only
@ 2023-04-05  9:19 Tankut Baris Aktemur via Gdb-patches
  2023-04-05  9:20 ` [PATCH 1/3] gdb: pass info_threads_opts to print_thread_info_1 Tankut Baris Aktemur via Gdb-patches
                   ` (4 more replies)
  0 siblings, 5 replies; 32+ messages in thread
From: Tankut Baris Aktemur via Gdb-patches @ 2023-04-05  9:19 UTC (permalink / raw)
  To: gdb-patches

Hi,

This is a short series that adds a "-stopped" option to the "info threads"
to show stopped threads only.

Regards
Baris


Tankut Baris Aktemur (3):
  gdb: pass info_threads_opts to print_thread_info_1
  gdb, doc: add the missing '-gid' option to 'info threads'
  gdb: add a '-stopped' option to "info threads"

 gdb/NEWS                                      |  7 ++
 gdb/doc/gdb.texinfo                           |  6 +-
 gdb/testsuite/gdb.base/options.exp            | 11 ++-
 .../gdb.threads/info-threads-stopped.c        | 78 +++++++++++++++++++
 .../gdb.threads/info-threads-stopped.exp      | 75 ++++++++++++++++++
 gdb/thread.c                                  | 76 +++++++++++-------
 6 files changed, 221 insertions(+), 32 deletions(-)
 create mode 100644 gdb/testsuite/gdb.threads/info-threads-stopped.c
 create mode 100644 gdb/testsuite/gdb.threads/info-threads-stopped.exp

-- 
2.25.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 1/3] gdb: pass info_threads_opts to print_thread_info_1
  2023-04-05  9:19 [PATCH 0/3] Option to show stopped threads only Tankut Baris Aktemur via Gdb-patches
@ 2023-04-05  9:20 ` Tankut Baris Aktemur via Gdb-patches
  2023-04-05  9:20 ` [PATCH 2/3] gdb, doc: add the missing '-gid' option to 'info threads' Tankut Baris Aktemur via Gdb-patches
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 32+ messages in thread
From: Tankut Baris Aktemur via Gdb-patches @ 2023-04-05  9:20 UTC (permalink / raw)
  To: gdb-patches

The "info threads" command tracks its options in a struct named
'info_threads_opts', which currently has only one option.  Pass the
whole options object to helper functions, instead of passing
the option value individually.  This is a refactoring to make adding
more options easier.
---
 gdb/thread.c | 61 +++++++++++++++++++++++++++-------------------------
 1 file changed, 32 insertions(+), 29 deletions(-)

diff --git a/gdb/thread.c b/gdb/thread.c
index 4d97ed3f2d1..57b3f7611e2 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -951,6 +951,24 @@ pc_in_thread_step_range (CORE_ADDR pc, struct thread_info *thread)
 	  && pc < thread->control.step_range_end);
 }
 
+/* The options for the "info threads" command.  */
+
+struct info_threads_opts
+{
+  /* For "-gid".  */
+  bool show_global_ids = false;
+};
+
+static const gdb::option::option_def info_threads_option_defs[] = {
+
+  gdb::option::flag_option_def<info_threads_opts> {
+    "gid",
+    [] (info_threads_opts *opts) { return &opts->show_global_ids; },
+    N_("Show global thread IDs."),
+  },
+
+};
+
 /* Helper for print_thread_info.  Returns true if THR should be
    printed.  If REQUESTED_THREADS, a list of GDB ids/ranges, is not
    NULL, only print THR if its ID is included in the list.  GLOBAL_IDS
@@ -959,11 +977,13 @@ pc_in_thread_step_range (CORE_ADDR pc, struct thread_info *thread)
    is a thread from the process PID.  Otherwise, threads from all
    attached PIDs are printed.  If both REQUESTED_THREADS is not NULL
    and PID is not -1, then the thread is printed if it belongs to the
-   specified process.  Otherwise, an error is raised.  */
+   specified process.  Otherwise, an error is raised.  OPTS is the
+   options of the "info threads" command.  */
 
 static bool
 should_print_thread (const char *requested_threads, int default_inf_num,
-		     int global_ids, int pid, struct thread_info *thr)
+		     int global_ids, int pid, thread_info *thr,
+		     info_threads_opts opts)
 {
   if (requested_threads != NULL && *requested_threads != '\0')
     {
@@ -1014,12 +1034,12 @@ thread_target_id_str (thread_info *tp)
 
 /* Like print_thread_info, but in addition, GLOBAL_IDS indicates
    whether REQUESTED_THREADS is a list of global or per-inferior
-   thread ids.  */
+   thread ids.  OPTS is the options of the "info threads" command.  */
 
 static void
 print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
 		     int global_ids, int pid,
-		     int show_global_ids)
+		     info_threads_opts opts)
 {
   int default_inf_num = current_inferior ()->num;
 
@@ -1055,7 +1075,7 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
 	for (thread_info *tp : all_threads ())
 	  {
 	    if (!should_print_thread (requested_threads, default_inf_num,
-				      global_ids, pid, tp))
+				      global_ids, pid, tp, opts))
 	      continue;
 
 	    /* Switch inferiors so we're looking at the right
@@ -1079,12 +1099,12 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
 	    return;
 	  }
 
-	table_emitter.emplace (uiout, show_global_ids ? 5 : 4,
+	table_emitter.emplace (uiout, opts.show_global_ids ? 5 : 4,
 			       n_threads, "threads");
 
 	uiout->table_header (1, ui_left, "current", "");
 	uiout->table_header (4, ui_left, "id-in-tg", "Id");
-	if (show_global_ids)
+	if (opts.show_global_ids)
 	  uiout->table_header (4, ui_left, "id", "GId");
 	uiout->table_header (target_id_col_width, ui_left,
 			     "target-id", "Target Id");
@@ -1102,7 +1122,7 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
 	    current_exited = true;
 
 	  if (!should_print_thread (requested_threads, default_inf_num,
-				    global_ids, pid, tp))
+				    global_ids, pid, tp, opts))
 	    continue;
 
 	  ui_out_emit_tuple tuple_emitter (uiout, NULL);
@@ -1117,7 +1137,7 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
 	      uiout->field_string ("id-in-tg", print_thread_id (tp));
 	    }
 
-	  if (show_global_ids || uiout->is_mi_like_p ())
+	  if (opts.show_global_ids || uiout->is_mi_like_p ())
 	    uiout->field_signed ("id", tp->global_num);
 
 	  /* Switch to the thread (and inferior / target).  */
@@ -1199,27 +1219,10 @@ void
 print_thread_info (struct ui_out *uiout, const char *requested_threads,
 		   int pid)
 {
-  print_thread_info_1 (uiout, requested_threads, 1, pid, 0);
+  info_threads_opts opts {false};
+  print_thread_info_1 (uiout, requested_threads, 1, pid, opts);
 }
 
-/* The options for the "info threads" command.  */
-
-struct info_threads_opts
-{
-  /* For "-gid".  */
-  bool show_global_ids = false;
-};
-
-static const gdb::option::option_def info_threads_option_defs[] = {
-
-  gdb::option::flag_option_def<info_threads_opts> {
-    "gid",
-    [] (info_threads_opts *opts) { return &opts->show_global_ids; },
-    N_("Show global thread IDs."),
-  },
-
-};
-
 /* Create an option_def_group for the "info threads" options, with
    IT_OPTS as context.  */
 
@@ -1244,7 +1247,7 @@ info_threads_command (const char *arg, int from_tty)
   gdb::option::process_options
     (&arg, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, grp);
 
-  print_thread_info_1 (current_uiout, arg, 0, -1, it_opts.show_global_ids);
+  print_thread_info_1 (current_uiout, arg, 0, -1, it_opts);
 }
 
 /* Completer for the "info threads" command.  */
-- 
2.25.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 2/3] gdb, doc: add the missing '-gid' option to 'info threads'
  2023-04-05  9:19 [PATCH 0/3] Option to show stopped threads only Tankut Baris Aktemur via Gdb-patches
  2023-04-05  9:20 ` [PATCH 1/3] gdb: pass info_threads_opts to print_thread_info_1 Tankut Baris Aktemur via Gdb-patches
@ 2023-04-05  9:20 ` Tankut Baris Aktemur via Gdb-patches
  2023-04-05  9:56   ` Eli Zaretskii via Gdb-patches
  2023-04-05  9:20 ` [PATCH 3/3] gdb: add a '-stopped' option to "info threads" Tankut Baris Aktemur via Gdb-patches
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 32+ messages in thread
From: Tankut Baris Aktemur via Gdb-patches @ 2023-04-05  9:20 UTC (permalink / raw)
  To: gdb-patches

The 'info threads' command does not show the '-gid' option
in the syntax.  Add the option.  The flag is already explained
in the command description and used in the examples.
---
 gdb/doc/gdb.texinfo | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index fe76e5e0a0e..ed14888b77b 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -3678,7 +3678,7 @@ Thread 1 "main" received signal SIGINT, Interrupt.
 @table @code
 @anchor{info_threads}
 @kindex info threads
-@item info threads @r{[}@var{thread-id-list}@r{]}
+@item info threads @r{[}-gid@r{]} @r{[}@var{thread-id-list}@r{]}
 
 Display information about one or more threads.  With no arguments
 displays information about all threads.  You can specify the list of
-- 
2.25.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 3/3] gdb: add a '-stopped' option to "info threads"
  2023-04-05  9:19 [PATCH 0/3] Option to show stopped threads only Tankut Baris Aktemur via Gdb-patches
  2023-04-05  9:20 ` [PATCH 1/3] gdb: pass info_threads_opts to print_thread_info_1 Tankut Baris Aktemur via Gdb-patches
  2023-04-05  9:20 ` [PATCH 2/3] gdb, doc: add the missing '-gid' option to 'info threads' Tankut Baris Aktemur via Gdb-patches
@ 2023-04-05  9:20 ` Tankut Baris Aktemur via Gdb-patches
  2023-04-05 10:00   ` Eli Zaretskii via Gdb-patches
  2025-03-18 18:04 ` [PATCH v2 0/2] Option to show stopped threads only Tankut Baris Aktemur
  2025-04-04 13:36 ` [PATCH v3 " Tankut Baris Aktemur
  4 siblings, 1 reply; 32+ messages in thread
From: Tankut Baris Aktemur via Gdb-patches @ 2023-04-05  9:20 UTC (permalink / raw)
  To: gdb-patches

Add a '-stopped' option to the "info threads" command to print stopped
threads only and skip the running ones.  This is a convenience flag to
filter out the running threads in programs that have many threads.

Suppose we have an application with 5 threads, 2 of which have hit a
breakpoint.  The "info threads" command in the non-stop mode gives:

  (gdb) info threads
    Id   Target Id             Frame
  * 1    Thread 0x7ffff7d99740 (running)
    2    Thread 0x7ffff7d98700 something () at file.c:30
    3    Thread 0x7ffff7597700 (running)
    4    Thread 0x7ffff6d96700 something () at file.c:30
    5    Thread 0x7ffff6595700 (running)
  (gdb)

Using the "-stopped" flag, we get

  (gdb) info threads -stopped
    Id   Target Id             Frame
    2    Thread 0x7ffff7d98700 something () at file.c:30
    4    Thread 0x7ffff6d96700 something () at file.c:30
  (gdb)

When combined with a thread ID, the behavior is as follows:

  (gdb) info threads 3
    Id   Target Id             Frame
    3    Thread 0x7ffff7597700 (running)
  (gdb) info threads -stopped 3
  No stopped threads match '3'.
  (gdb)

Regression-tested on X86_64 Linux.
---
 gdb/NEWS                                      |  7 ++
 gdb/doc/gdb.texinfo                           |  6 +-
 gdb/testsuite/gdb.base/options.exp            | 11 ++-
 .../gdb.threads/info-threads-stopped.c        | 78 +++++++++++++++++++
 .../gdb.threads/info-threads-stopped.exp      | 75 ++++++++++++++++++
 gdb/thread.c                                  | 17 +++-
 6 files changed, 190 insertions(+), 4 deletions(-)
 create mode 100644 gdb/testsuite/gdb.threads/info-threads-stopped.c
 create mode 100644 gdb/testsuite/gdb.threads/info-threads-stopped.exp

diff --git a/gdb/NEWS b/gdb/NEWS
index 10a1a70fa52..33b104fda72 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -96,6 +96,13 @@ info main
    $2 = 1
    (gdb) break func if $_shell("some command") == 0
 
+* Changed commands
+
+info threads [-gid] [-stopped] [ID]...
+  This command now takes an optional flag, '-stopped', that causes only
+  the stopped threads to be printed.  The flag can be useful to get a
+  reduced list when there is a large number of unstopped threads.
+
 * MI changes
 
 ** mi now reports 'no-history' as a stop reason when hitting the end of the
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index ed14888b77b..02f6a9eb49a 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -3678,7 +3678,7 @@ Thread 1 "main" received signal SIGINT, Interrupt.
 @table @code
 @anchor{info_threads}
 @kindex info threads
-@item info threads @r{[}-gid@r{]} @r{[}@var{thread-id-list}@r{]}
+@item info threads @r{[}-gid@r{]} @r{[}-stopped@r{]} @r{[}@var{thread-id-list}@r{]}
 
 Display information about one or more threads.  With no arguments
 displays information about all threads.  You can specify the list of
@@ -3728,6 +3728,10 @@ If you're debugging multiple inferiors, @value{GDBN} displays thread
 IDs using the qualified @var{inferior-num}.@var{thread-num} format.
 Otherwise, only @var{thread-num} is shown.
 
+If you specify the @samp{-stopped} option, @value{GDBN} displays the
+stopped threads only.  This can be helpful to reduce the output list
+if there is a large number of unstopped threads.
+
 If you specify the @samp{-gid} option, @value{GDBN} displays a column
 indicating each thread's global thread ID:
 
diff --git a/gdb/testsuite/gdb.base/options.exp b/gdb/testsuite/gdb.base/options.exp
index 6d90615710e..58c85567a4e 100644
--- a/gdb/testsuite/gdb.base/options.exp
+++ b/gdb/testsuite/gdb.base/options.exp
@@ -492,12 +492,21 @@ proc_with_prefix test-thread-apply {} {
 proc_with_prefix test-info-threads {} {
     test_gdb_complete_multiple "info threads " "" "" {
 	"-gid"
+	"-stopped"
 	"ID"
     }
 
+    test_gdb_complete_multiple "info threads " "-" "" {
+	"-gid"
+	"-stopped"
+    }
+
     test_gdb_complete_unique \
-	"info threads -" \
+	"info threads -g" \
 	"info threads -gid"
+    test_gdb_complete_unique \
+	"info threads -s" \
+	"info threads -stopped"
 
     # "ID" isn't really something the user can type.
     test_gdb_complete_none "info threads I"
diff --git a/gdb/testsuite/gdb.threads/info-threads-stopped.c b/gdb/testsuite/gdb.threads/info-threads-stopped.c
new file mode 100644
index 00000000000..42ca8cf0b69
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/info-threads-stopped.c
@@ -0,0 +1,78 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2022-2023 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#define NUM 4
+
+volatile int should_spin = 1;
+
+static void
+something ()
+{
+}
+
+static void
+spin ()
+{
+  while (should_spin)
+    usleep (1);
+}
+
+static void *
+work (void *arg)
+{
+  int id = *((int *) arg);
+
+  /* Sleep a bit to give the other threads a chance to run.  */
+  usleep (1);
+
+  if (id % 2 == 0)
+    something (); /* break-here */
+  else
+    spin ();
+
+  pthread_exit (NULL);
+}
+
+int
+main ()
+{
+  /* Ensure we stop if GDB crashes and DejaGNU fails to kill us.  */
+  alarm (10);
+
+  pthread_t threads[NUM];
+  void *thread_result;
+  int ids[NUM];
+
+  for (int i = 0; i < NUM; i++)
+    {
+      ids[i] = i + 2;
+      pthread_create (&threads[i], NULL, work, &(ids[i]));
+    }
+
+  sleep (10);
+  should_spin = 0;
+
+  for (int i = 0; i < NUM; i++)
+    pthread_join(threads[i], &thread_result);
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.threads/info-threads-stopped.exp b/gdb/testsuite/gdb.threads/info-threads-stopped.exp
new file mode 100644
index 00000000000..5643a513aff
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/info-threads-stopped.exp
@@ -0,0 +1,75 @@
+# Copyright (C) 2022-2023 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test for the '-stopped' flag of the "info threads" command.
+
+standard_testfile
+
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
+	 executable debug] != "" } {
+    return -1
+}
+
+save_vars { GDBFLAGS } {
+    append GDBFLAGS " -ex \"set non-stop on\""
+    clean_restart $binfile
+}
+
+gdb_breakpoint "something"
+gdb_run_cmd
+
+# Two threads hit the bp.
+set fill "\[^\r\n\]+"
+set num_hits 0
+gdb_test_multiple "" "hit the breakpoint" -lbl {
+    -re "\r\nThread ${fill} hit Breakpoint 1${fill}" {
+	incr num_hits
+	if {$num_hits < 2} {
+	    exp_continue
+	}
+    }
+    -re "\r\n$gdb_prompt " {
+	exp_continue
+    }
+}
+gdb_assert {$num_hits == 2} "two threads hit the bp"
+
+# Count the number of running/stopped threads reported
+# by the "info threads" command.
+foreach flag {"" "-stopped"} {
+    set num_running 0
+    set num_stopped 0
+    gdb_test_multiple "info threads $flag" "info threads $flag" {
+	-re "Id${fill}Target Id${fill}Frame${fill}" {
+	    exp_continue
+	}
+	-re "^\r\n. ${decimal}${fill}Thread ${fill}.running." {
+	    incr num_running
+	    exp_continue
+	}
+	-re "^\r\n. ${decimal}${fill}Thread ${fill}something ${fill}" {
+	    incr num_stopped
+	    exp_continue
+	}
+	-re "^\r\n$gdb_prompt $" {
+	    gdb_assert {$num_stopped == 2} "$gdb_test_name: num stopped"
+	    if {$flag eq ""} {
+		gdb_assert {$num_running == 3} "$gdb_test_name: num running"
+	    } else {
+		gdb_assert {$num_running == 0} "$gdb_test_name: num running"
+	    }
+	}
+    }
+}
diff --git a/gdb/thread.c b/gdb/thread.c
index 57b3f7611e2..8886bd45674 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -957,6 +957,8 @@ struct info_threads_opts
 {
   /* For "-gid".  */
   bool show_global_ids = false;
+  /* For "-stopped".  */
+  bool show_stopped_threads = false;
 };
 
 static const gdb::option::option_def info_threads_option_defs[] = {
@@ -966,6 +968,11 @@ static const gdb::option::option_def info_threads_option_defs[] = {
     [] (info_threads_opts *opts) { return &opts->show_global_ids; },
     N_("Show global thread IDs."),
   },
+  gdb::option::flag_option_def<info_threads_opts> {
+    "stopped",
+    [] (info_threads_opts *opts) { return &opts->show_stopped_threads; },
+    N_("Show stopped threads only."),
+  },
 
 };
 
@@ -1008,6 +1015,11 @@ should_print_thread (const char *requested_threads, int default_inf_num,
   if (thr->state == THREAD_EXITED)
     return false;
 
+  /* Skip a running thread if the user wants stopped threads only.  */
+  bool is_stopped = (thr->state == THREAD_STOPPED);
+  if (opts.show_stopped_threads && !is_stopped)
+    return false;
+
   return true;
 }
 
@@ -1094,7 +1106,8 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
 	    if (requested_threads == NULL || *requested_threads == '\0')
 	      uiout->message (_("No threads.\n"));
 	    else
-	      uiout->message (_("No threads match '%s'.\n"),
+	      uiout->message (_("No %sthreads match '%s'.\n"),
+			      (opts.show_stopped_threads ? "stopped " : ""),
 			      requested_threads);
 	    return;
 	  }
@@ -1219,7 +1232,7 @@ void
 print_thread_info (struct ui_out *uiout, const char *requested_threads,
 		   int pid)
 {
-  info_threads_opts opts {false};
+  info_threads_opts opts {false, false};
   print_thread_info_1 (uiout, requested_threads, 1, pid, opts);
 }
 
-- 
2.25.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 2/3] gdb, doc: add the missing '-gid' option to 'info threads'
  2023-04-05  9:20 ` [PATCH 2/3] gdb, doc: add the missing '-gid' option to 'info threads' Tankut Baris Aktemur via Gdb-patches
@ 2023-04-05  9:56   ` Eli Zaretskii via Gdb-patches
  2023-04-05 10:12     ` Aktemur, Tankut Baris via Gdb-patches
  0 siblings, 1 reply; 32+ messages in thread
From: Eli Zaretskii via Gdb-patches @ 2023-04-05  9:56 UTC (permalink / raw)
  To: Tankut Baris Aktemur; +Cc: gdb-patches

> Date: Wed,  5 Apr 2023 11:20:01 +0200
> From: Tankut Baris Aktemur via Gdb-patches <gdb-patches@sourceware.org>
> 
> The 'info threads' command does not show the '-gid' option
> in the syntax.  Add the option.  The flag is already explained
> in the command description and used in the examples.
> ---
>  gdb/doc/gdb.texinfo | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index fe76e5e0a0e..ed14888b77b 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -3678,7 +3678,7 @@ Thread 1 "main" received signal SIGINT, Interrupt.
>  @table @code
>  @anchor{info_threads}
>  @kindex info threads
> -@item info threads @r{[}@var{thread-id-list}@r{]}
> +@item info threads @r{[}-gid@r{]} @r{[}@var{thread-id-list}@r{]}
>  
>  Display information about one or more threads.  With no arguments
>  displays information about all threads.  You can specify the list of

Thanks, this is OK.

Approved-By: Eli Zaretskii <eliz@gnu.org>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 3/3] gdb: add a '-stopped' option to "info threads"
  2023-04-05  9:20 ` [PATCH 3/3] gdb: add a '-stopped' option to "info threads" Tankut Baris Aktemur via Gdb-patches
@ 2023-04-05 10:00   ` Eli Zaretskii via Gdb-patches
  2023-04-05 10:19     ` Aktemur, Tankut Baris via Gdb-patches
  0 siblings, 1 reply; 32+ messages in thread
From: Eli Zaretskii via Gdb-patches @ 2023-04-05 10:00 UTC (permalink / raw)
  To: Tankut Baris Aktemur; +Cc: gdb-patches

> Date: Wed,  5 Apr 2023 11:20:02 +0200
> From: Tankut Baris Aktemur via Gdb-patches <gdb-patches@sourceware.org>
> 
>  gdb/NEWS                                      |  7 ++
>  gdb/doc/gdb.texinfo                           |  6 +-
>  gdb/testsuite/gdb.base/options.exp            | 11 ++-
>  .../gdb.threads/info-threads-stopped.c        | 78 +++++++++++++++++++
>  .../gdb.threads/info-threads-stopped.exp      | 75 ++++++++++++++++++
>  gdb/thread.c                                  | 17 +++-
>  6 files changed, 190 insertions(+), 4 deletions(-)
>  create mode 100644 gdb/testsuite/gdb.threads/info-threads-stopped.c
>  create mode 100644 gdb/testsuite/gdb.threads/info-threads-stopped.exp

Thanks, the documentation parts are OK.

But I have a question about the new behavior:

>   (gdb) info threads -stopped 3
>   No stopped threads match '3'.

Is it really useful to show nothing and emit an error message if
explicit thread IDs were specified by the user?  Wouldn't it be better
to ignore the -stopped switch in that case?

Reviewed-By: Eli Zaretskii <eliz@gnu.org>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* RE: [PATCH 2/3] gdb, doc: add the missing '-gid' option to 'info threads'
  2023-04-05  9:56   ` Eli Zaretskii via Gdb-patches
@ 2023-04-05 10:12     ` Aktemur, Tankut Baris via Gdb-patches
  0 siblings, 0 replies; 32+ messages in thread
From: Aktemur, Tankut Baris via Gdb-patches @ 2023-04-05 10:12 UTC (permalink / raw)
  To: Eli Zaretskii, gdb-patches

On Wednesday, April 5, 2023 11:57 AM, Eli Zaretskii wrote:
> > Date: Wed,  5 Apr 2023 11:20:01 +0200
> > From: Tankut Baris Aktemur via Gdb-patches <gdb-patches@sourceware.org>
> >
> > The 'info threads' command does not show the '-gid' option
> > in the syntax.  Add the option.  The flag is already explained
> > in the command description and used in the examples.
> > ---
> >  gdb/doc/gdb.texinfo | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> > index fe76e5e0a0e..ed14888b77b 100644
> > --- a/gdb/doc/gdb.texinfo
> > +++ b/gdb/doc/gdb.texinfo
> > @@ -3678,7 +3678,7 @@ Thread 1 "main" received signal SIGINT, Interrupt.
> >  @table @code
> >  @anchor{info_threads}
> >  @kindex info threads
> > -@item info threads @r{[}@var{thread-id-list}@r{]}
> > +@item info threads @r{[}-gid@r{]} @r{[}@var{thread-id-list}@r{]}
> >
> >  Display information about one or more threads.  With no arguments
> >  displays information about all threads.  You can specify the list of
> 
> Thanks, this is OK.
> 
> Approved-By: Eli Zaretskii <eliz@gnu.org>

Thank you.  I pushed this single patch.

-Baris

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 32+ messages in thread

* RE: [PATCH 3/3] gdb: add a '-stopped' option to "info threads"
  2023-04-05 10:00   ` Eli Zaretskii via Gdb-patches
@ 2023-04-05 10:19     ` Aktemur, Tankut Baris via Gdb-patches
  2023-04-05 10:50       ` Eli Zaretskii via Gdb-patches
  0 siblings, 1 reply; 32+ messages in thread
From: Aktemur, Tankut Baris via Gdb-patches @ 2023-04-05 10:19 UTC (permalink / raw)
  To: Eli Zaretskii, gdb-patches

On Wednesday, April 5, 2023 12:01 PM, Eli Zaretskii wrote:
> > Date: Wed,  5 Apr 2023 11:20:02 +0200
> > From: Tankut Baris Aktemur via Gdb-patches <gdb-patches@sourceware.org>
> >
> >  gdb/NEWS                                      |  7 ++
> >  gdb/doc/gdb.texinfo                           |  6 +-
> >  gdb/testsuite/gdb.base/options.exp            | 11 ++-
> >  .../gdb.threads/info-threads-stopped.c        | 78 +++++++++++++++++++
> >  .../gdb.threads/info-threads-stopped.exp      | 75 ++++++++++++++++++
> >  gdb/thread.c                                  | 17 +++-
> >  6 files changed, 190 insertions(+), 4 deletions(-)
> >  create mode 100644 gdb/testsuite/gdb.threads/info-threads-stopped.c
> >  create mode 100644 gdb/testsuite/gdb.threads/info-threads-stopped.exp
> 
> Thanks, the documentation parts are OK.
> 
> But I have a question about the new behavior:
> 
> >   (gdb) info threads -stopped 3
> >   No stopped threads match '3'.
> 
> Is it really useful to show nothing and emit an error message if
> explicit thread IDs were specified by the user?  Wouldn't it be better
> to ignore the -stopped switch in that case?
> 
> Reviewed-By: Eli Zaretskii <eliz@gnu.org>

The user may have given a thread id range or a wildcard, like
"info threads -stopped 1-999" or "info threads -stopped 2.*".
Ignoring the flag for these cases can output a very long list.

I'm fine if we make the single thread id a special case.  But then
the question is, where do we draw the line?  If the user gave just a
few thread ids, do we still ignore the flag?  What is the limit to
the acceptable list length?  Because of these questions, consistently
applying the flag made more sense to me.

Regards
-Baris


Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 3/3] gdb: add a '-stopped' option to "info threads"
  2023-04-05 10:19     ` Aktemur, Tankut Baris via Gdb-patches
@ 2023-04-05 10:50       ` Eli Zaretskii via Gdb-patches
  2023-04-05 11:31         ` Aktemur, Tankut Baris via Gdb-patches
  0 siblings, 1 reply; 32+ messages in thread
From: Eli Zaretskii via Gdb-patches @ 2023-04-05 10:50 UTC (permalink / raw)
  To: Aktemur, Tankut Baris; +Cc: gdb-patches

> From: "Aktemur, Tankut Baris" <tankut.baris.aktemur@intel.com>
> Date: Wed, 5 Apr 2023 10:19:26 +0000
> 
> I'm fine if we make the single thread id a special case.

Maybe that's all we should do.

> But then the question is, where do we draw the line?  If the user
> gave just a few thread ids, do we still ignore the flag?  What is
> the limit to the acceptable list length?  Because of these
> questions, consistently applying the flag made more sense to me.

We don't have to be 100% consistent, we just need to be useful.

^ permalink raw reply	[flat|nested] 32+ messages in thread

* RE: [PATCH 3/3] gdb: add a '-stopped' option to "info threads"
  2023-04-05 10:50       ` Eli Zaretskii via Gdb-patches
@ 2023-04-05 11:31         ` Aktemur, Tankut Baris via Gdb-patches
  2023-04-05 11:56           ` Eli Zaretskii via Gdb-patches
  2025-04-24 14:50           ` Pedro Alves
  0 siblings, 2 replies; 32+ messages in thread
From: Aktemur, Tankut Baris via Gdb-patches @ 2023-04-05 11:31 UTC (permalink / raw)
  To: Eli Zaretskii, gdb-patches

On Wednesday, April 5, 2023 12:51 PM, Eli Zaretskii wrote:
> > From: "Aktemur, Tankut Baris" <tankut.baris.aktemur@intel.com>
> > Date: Wed, 5 Apr 2023 10:19:26 +0000
> >
> > I'm fine if we make the single thread id a special case.
> 
> Maybe that's all we should do.
> 
> > But then the question is, where do we draw the line?  If the user
> > gave just a few thread ids, do we still ignore the flag?  What is
> > the limit to the acceptable list length?  Because of these
> > questions, consistently applying the flag made more sense to me.
> 
> We don't have to be 100% consistent, we just need to be useful.

Let's please wait a bit in case other maintainers want to chime in.
I don't have an objection to treating the single thread id case specially.

-Baris

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 3/3] gdb: add a '-stopped' option to "info threads"
  2023-04-05 11:31         ` Aktemur, Tankut Baris via Gdb-patches
@ 2023-04-05 11:56           ` Eli Zaretskii via Gdb-patches
  2025-04-24 14:50           ` Pedro Alves
  1 sibling, 0 replies; 32+ messages in thread
From: Eli Zaretskii via Gdb-patches @ 2023-04-05 11:56 UTC (permalink / raw)
  To: Aktemur, Tankut Baris; +Cc: gdb-patches

> From: "Aktemur, Tankut Baris" <tankut.baris.aktemur@intel.com>
> Date: Wed, 5 Apr 2023 11:31:16 +0000
> 
> On Wednesday, April 5, 2023 12:51 PM, Eli Zaretskii wrote:
> > > From: "Aktemur, Tankut Baris" <tankut.baris.aktemur@intel.com>
> > > Date: Wed, 5 Apr 2023 10:19:26 +0000
> > >
> > > I'm fine if we make the single thread id a special case.
> > 
> > Maybe that's all we should do.
> > 
> > > But then the question is, where do we draw the line?  If the user
> > > gave just a few thread ids, do we still ignore the flag?  What is
> > > the limit to the acceptable list length?  Because of these
> > > questions, consistently applying the flag made more sense to me.
> > 
> > We don't have to be 100% consistent, we just need to be useful.
> 
> Let's please wait a bit in case other maintainers want to chime in.

Sure.  I just expressed my personal opinion, not a request to make
changes in your patches right away.

^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH v2 0/2] Option to show stopped threads only
  2023-04-05  9:19 [PATCH 0/3] Option to show stopped threads only Tankut Baris Aktemur via Gdb-patches
                   ` (2 preceding siblings ...)
  2023-04-05  9:20 ` [PATCH 3/3] gdb: add a '-stopped' option to "info threads" Tankut Baris Aktemur via Gdb-patches
@ 2025-03-18 18:04 ` Tankut Baris Aktemur
  2025-03-18 18:05   ` [PATCH v2 1/2] gdb: pass info_threads_opts to print_thread_info_1 Tankut Baris Aktemur
                     ` (2 more replies)
  2025-04-04 13:36 ` [PATCH v3 " Tankut Baris Aktemur
  4 siblings, 3 replies; 32+ messages in thread
From: Tankut Baris Aktemur @ 2025-03-18 18:04 UTC (permalink / raw)
  To: gdb-patches

Hi,

This is the rebased version of

  https://inbox.sourceware.org/gdb-patches/cover.1680686220.git.tankut.baris.aktemur@intel.com/

As a comment, Eli had expressed his view that when "info threads" is
given a single thread ID, the "-stopped" flag could be ignored.  I
didn't implement this yet but can gladly do that if that's the general
preference.

Regards,
Baris

Tankut Baris Aktemur (2):
  gdb: pass info_threads_opts to print_thread_info_1
  gdb: add a '-stopped' option to "info threads"

 gdb/NEWS                                      |  7 ++
 gdb/doc/gdb.texinfo                           |  6 +-
 gdb/testsuite/gdb.base/options.exp            | 11 ++-
 .../gdb.threads/info-threads-stopped.c        | 78 +++++++++++++++++
 .../gdb.threads/info-threads-stopped.exp      | 75 ++++++++++++++++
 gdb/thread.c                                  | 86 +++++++++++--------
 6 files changed, 226 insertions(+), 37 deletions(-)
 create mode 100644 gdb/testsuite/gdb.threads/info-threads-stopped.c
 create mode 100644 gdb/testsuite/gdb.threads/info-threads-stopped.exp

-- 
2.34.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Sean Fennelly, Jeffrey Schneiderman, Tiffany Doon Silva
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH v2 1/2] gdb: pass info_threads_opts to print_thread_info_1
  2025-03-18 18:04 ` [PATCH v2 0/2] Option to show stopped threads only Tankut Baris Aktemur
@ 2025-03-18 18:05   ` Tankut Baris Aktemur
  2025-03-18 18:05   ` [PATCH v2 2/2] gdb: add a '-stopped' option to "info threads" Tankut Baris Aktemur
  2025-03-28 16:38   ` [PATCH v2 0/2] Option to show stopped threads only Guinevere Larsen
  2 siblings, 0 replies; 32+ messages in thread
From: Tankut Baris Aktemur @ 2025-03-18 18:05 UTC (permalink / raw)
  To: gdb-patches

The "info threads" command tracks its options in a struct named
'info_threads_opts', which currently has only one option.  Pass the
whole options object to helper functions, instead of passing
the option value individually.  This is a refactoring to make adding
more options easier.
---
 gdb/thread.c | 71 +++++++++++++++++++++++++++-------------------------
 1 file changed, 37 insertions(+), 34 deletions(-)

diff --git a/gdb/thread.c b/gdb/thread.c
index 8a34671bb6c..7dc8e7018c5 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -1038,6 +1038,24 @@ pc_in_thread_step_range (CORE_ADDR pc, struct thread_info *thread)
 	  && pc < thread->control.step_range_end);
 }
 
+/* The options for the "info threads" command.  */
+
+struct info_threads_opts
+{
+  /* For "-gid".  */
+  bool show_global_ids = false;
+};
+
+static const gdb::option::option_def info_threads_option_defs[] = {
+
+  gdb::option::flag_option_def<info_threads_opts> {
+    "gid",
+    [] (info_threads_opts *opts) { return &opts->show_global_ids; },
+    N_("Show global thread IDs."),
+  },
+
+};
+
 /* Helper for print_thread_info.  Returns true if THR should be
    printed.  If REQUESTED_THREADS, a list of GDB ids/ranges, is not
    NULL, only print THR if its ID is included in the list.  GLOBAL_IDS
@@ -1046,11 +1064,13 @@ pc_in_thread_step_range (CORE_ADDR pc, struct thread_info *thread)
    is a thread from the process PID.  Otherwise, threads from all
    attached PIDs are printed.  If both REQUESTED_THREADS is not NULL
    and PID is not -1, then the thread is printed if it belongs to the
-   specified process.  Otherwise, an error is raised.  */
+   specified process.  Otherwise, an error is raised.  OPTS is the
+   options of the "info threads" command.  */
 
 static bool
 should_print_thread (const char *requested_threads, int default_inf_num,
-		     int global_ids, int pid, struct thread_info *thr)
+		     int global_ids, int pid, thread_info *thr,
+		     info_threads_opts opts)
 {
   if (requested_threads != NULL && *requested_threads != '\0')
     {
@@ -1104,7 +1124,7 @@ thread_target_id_str (thread_info *tp)
 
 static void
 do_print_thread (ui_out *uiout, const char *requested_threads,
-		 int global_ids, int pid, int show_global_ids,
+		 int global_ids, int pid, info_threads_opts opts,
 		 int default_inf_num, thread_info *tp,
 		 thread_info *current_thread)
 {
@@ -1115,7 +1135,7 @@ do_print_thread (ui_out *uiout, const char *requested_threads,
     switch_to_thread (current_thread);
 
   if (!should_print_thread (requested_threads, default_inf_num,
-			    global_ids, pid, tp))
+			    global_ids, pid, tp, opts))
     return;
 
   ui_out_emit_tuple tuple_emitter (uiout, NULL);
@@ -1130,7 +1150,7 @@ do_print_thread (ui_out *uiout, const char *requested_threads,
       uiout->field_string ("id-in-tg", print_thread_id (tp));
     }
 
-  if (show_global_ids || uiout->is_mi_like_p ())
+  if (opts.show_global_ids || uiout->is_mi_like_p ())
     uiout->field_signed ("id", tp->global_num);
 
   /* Switch to the thread (and inferior / target).  */
@@ -1191,23 +1211,23 @@ do_print_thread (ui_out *uiout, const char *requested_threads,
 
 static void
 print_thread (ui_out *uiout, const char *requested_threads,
-	      int global_ids, int pid, int show_global_ids,
+	      int global_ids, int pid, info_threads_opts opts,
 	      int default_inf_num, thread_info *tp, thread_info *current_thread)
 
 {
   do_with_buffered_output (do_print_thread, uiout, requested_threads,
-			   global_ids, pid, show_global_ids,
-			   default_inf_num, tp, current_thread);
+			   global_ids, pid, opts, default_inf_num, tp,
+			   current_thread);
 }
 
 /* Like print_thread_info, but in addition, GLOBAL_IDS indicates
    whether REQUESTED_THREADS is a list of global or per-inferior
-   thread ids.  */
+   thread ids.  OPTS is the options of the "info threads" command.  */
 
 static void
 print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
 		     int global_ids, int pid,
-		     int show_global_ids)
+		     info_threads_opts opts)
 {
   int default_inf_num = current_inferior ()->num;
 
@@ -1247,7 +1267,7 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
 	      switch_to_thread (current_thread);
 
 	    if (!should_print_thread (requested_threads, default_inf_num,
-				      global_ids, pid, tp))
+				      global_ids, pid, tp, opts))
 	      continue;
 
 	    /* Switch inferiors so we're looking at the right
@@ -1271,12 +1291,12 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
 	    return;
 	  }
 
-	table_emitter.emplace (uiout, show_global_ids ? 5 : 4,
+	table_emitter.emplace (uiout, opts.show_global_ids ? 5 : 4,
 			       n_threads, "threads");
 
 	uiout->table_header (1, ui_left, "current", "");
 	uiout->table_header (4, ui_left, "id-in-tg", "Id");
-	if (show_global_ids)
+	if (opts.show_global_ids)
 	  uiout->table_header (4, ui_left, "id", "GId");
 	uiout->table_header (target_id_col_width, ui_left,
 			     "target-id", "Target Id");
@@ -1293,7 +1313,7 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
 	    current_exited = true;
 
 	  print_thread (uiout, requested_threads, global_ids, pid,
-			show_global_ids, default_inf_num, tp, current_thread);
+			opts, default_inf_num, tp, current_thread);
 	}
 
     /* This end scope restores the current thread and the frame
@@ -1322,27 +1342,10 @@ void
 print_thread_info (struct ui_out *uiout, const char *requested_threads,
 		   int pid)
 {
-  print_thread_info_1 (uiout, requested_threads, 1, pid, 0);
+  info_threads_opts opts {false};
+  print_thread_info_1 (uiout, requested_threads, 1, pid, opts);
 }
 
-/* The options for the "info threads" command.  */
-
-struct info_threads_opts
-{
-  /* For "-gid".  */
-  bool show_global_ids = false;
-};
-
-static const gdb::option::option_def info_threads_option_defs[] = {
-
-  gdb::option::flag_option_def<info_threads_opts> {
-    "gid",
-    [] (info_threads_opts *opts) { return &opts->show_global_ids; },
-    N_("Show global thread IDs."),
-  },
-
-};
-
 /* Create an option_def_group for the "info threads" options, with
    IT_OPTS as context.  */
 
@@ -1367,7 +1370,7 @@ info_threads_command (const char *arg, int from_tty)
   gdb::option::process_options
     (&arg, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, grp);
 
-  print_thread_info_1 (current_uiout, arg, 0, -1, it_opts.show_global_ids);
+  print_thread_info_1 (current_uiout, arg, 0, -1, it_opts);
 }
 
 /* Completer for the "info threads" command.  */
-- 
2.34.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Sean Fennelly, Jeffrey Schneiderman, Tiffany Doon Silva
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH v2 2/2] gdb: add a '-stopped' option to "info threads"
  2025-03-18 18:04 ` [PATCH v2 0/2] Option to show stopped threads only Tankut Baris Aktemur
  2025-03-18 18:05   ` [PATCH v2 1/2] gdb: pass info_threads_opts to print_thread_info_1 Tankut Baris Aktemur
@ 2025-03-18 18:05   ` Tankut Baris Aktemur
  2025-03-28 16:38   ` [PATCH v2 0/2] Option to show stopped threads only Guinevere Larsen
  2 siblings, 0 replies; 32+ messages in thread
From: Tankut Baris Aktemur @ 2025-03-18 18:05 UTC (permalink / raw)
  To: gdb-patches

Add a '-stopped' option to the "info threads" command to print stopped
threads only and skip the running ones.  This is a convenience flag to
filter out the running threads in programs that have many threads.

Suppose we have an application with 5 threads, 2 of which have hit a
breakpoint.  The "info threads" command in the non-stop mode gives:

  (gdb) info threads
    Id   Target Id             Frame
  * 1    Thread 0x7ffff7d99740 (running)
    2    Thread 0x7ffff7d98700 something () at file.c:30
    3    Thread 0x7ffff7597700 (running)
    4    Thread 0x7ffff6d96700 something () at file.c:30
    5    Thread 0x7ffff6595700 (running)
  (gdb)

Using the "-stopped" flag, we get

  (gdb) info threads -stopped
    Id   Target Id             Frame
    2    Thread 0x7ffff7d98700 something () at file.c:30
    4    Thread 0x7ffff6d96700 something () at file.c:30
  (gdb)

When combined with a thread ID, the behavior is as follows:

  (gdb) info threads 3
    Id   Target Id             Frame
    3    Thread 0x7ffff7597700 (running)
  (gdb) info threads -stopped 3
  No stopped threads match '3'.
  (gdb)

Regression-tested on X86_64 Linux.

Reviewed-By: Eli Zaretskii <eliz@gnu.org>
---
 gdb/NEWS                                      |  7 ++
 gdb/doc/gdb.texinfo                           |  6 +-
 gdb/testsuite/gdb.base/options.exp            | 11 ++-
 .../gdb.threads/info-threads-stopped.c        | 78 +++++++++++++++++++
 .../gdb.threads/info-threads-stopped.exp      | 75 ++++++++++++++++++
 gdb/thread.c                                  | 17 +++-
 6 files changed, 190 insertions(+), 4 deletions(-)
 create mode 100644 gdb/testsuite/gdb.threads/info-threads-stopped.c
 create mode 100644 gdb/testsuite/gdb.threads/info-threads-stopped.exp

diff --git a/gdb/NEWS b/gdb/NEWS
index 0aac7a7b13a..be24ed0a251 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -45,6 +45,13 @@ show riscv numeric-register-names
   (e.g 'x1') or their abi names (e.g. 'ra').
   Defaults to 'off', matching the old behaviour (abi names).
 
+* Changed commands
+
+info threads [-gid] [-stopped] [ID]...
+  This command now takes an optional flag, '-stopped', that causes only
+  the stopped threads to be printed.  The flag can be useful to get a
+  reduced list when there is a large number of unstopped threads.
+
 * Python API
 
   ** New class gdb.Color for dealing with colors.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 473431011d1..537e2e2230b 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -3807,7 +3807,7 @@ Thread 1 "main" received signal SIGINT, Interrupt.
 @table @code
 @anchor{info_threads}
 @kindex info threads
-@item info threads @r{[}-gid@r{]} @r{[}@var{thread-id-list}@r{]}
+@item info threads @r{[}-gid@r{]} @r{[}-stopped@r{]} @r{[}@var{thread-id-list}@r{]}
 
 Display information about one or more threads.  With no arguments
 displays information about all threads.  You can specify the list of
@@ -3857,6 +3857,10 @@ If you're debugging multiple inferiors, @value{GDBN} displays thread
 IDs using the qualified @var{inferior-num}.@var{thread-num} format.
 Otherwise, only @var{thread-num} is shown.
 
+If you specify the @samp{-stopped} option, @value{GDBN} displays the
+stopped threads only.  This can be helpful to reduce the output list
+if there is a large number of unstopped threads.
+
 If you specify the @samp{-gid} option, @value{GDBN} displays a column
 indicating each thread's global thread ID:
 
diff --git a/gdb/testsuite/gdb.base/options.exp b/gdb/testsuite/gdb.base/options.exp
index a1ca39eab11..a343867f189 100644
--- a/gdb/testsuite/gdb.base/options.exp
+++ b/gdb/testsuite/gdb.base/options.exp
@@ -508,12 +508,21 @@ proc_with_prefix test-thread-apply {} {
 proc_with_prefix test-info-threads {} {
     test_gdb_complete_multiple "info threads " "" "" {
 	"-gid"
+	"-stopped"
 	"ID"
     }
 
+    test_gdb_complete_multiple "info threads " "-" "" {
+	"-gid"
+	"-stopped"
+    }
+
     test_gdb_complete_unique \
-	"info threads -" \
+	"info threads -g" \
 	"info threads -gid"
+    test_gdb_complete_unique \
+	"info threads -s" \
+	"info threads -stopped"
 
     # "ID" isn't really something the user can type.
     test_gdb_complete_none "info threads I"
diff --git a/gdb/testsuite/gdb.threads/info-threads-stopped.c b/gdb/testsuite/gdb.threads/info-threads-stopped.c
new file mode 100644
index 00000000000..2c38ecca074
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/info-threads-stopped.c
@@ -0,0 +1,78 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2022-2025 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#define NUM 4
+
+volatile int should_spin = 1;
+
+static void
+something ()
+{
+}
+
+static void
+spin ()
+{
+  while (should_spin)
+    usleep (1);
+}
+
+static void *
+work (void *arg)
+{
+  int id = *((int *) arg);
+
+  /* Sleep a bit to give the other threads a chance to run.  */
+  usleep (1);
+
+  if (id % 2 == 0)
+    something (); /* break-here */
+  else
+    spin ();
+
+  pthread_exit (NULL);
+}
+
+int
+main ()
+{
+  /* Ensure we stop if GDB crashes and DejaGNU fails to kill us.  */
+  alarm (10);
+
+  pthread_t threads[NUM];
+  void *thread_result;
+  int ids[NUM];
+
+  for (int i = 0; i < NUM; i++)
+    {
+      ids[i] = i + 2;
+      pthread_create (&threads[i], NULL, work, &(ids[i]));
+    }
+
+  sleep (10);
+  should_spin = 0;
+
+  for (int i = 0; i < NUM; i++)
+    pthread_join(threads[i], &thread_result);
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.threads/info-threads-stopped.exp b/gdb/testsuite/gdb.threads/info-threads-stopped.exp
new file mode 100644
index 00000000000..3e6476c2f41
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/info-threads-stopped.exp
@@ -0,0 +1,75 @@
+# Copyright (C) 2022-2025 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test for the '-stopped' flag of the "info threads" command.
+
+standard_testfile
+
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
+	 executable debug] != "" } {
+    return -1
+}
+
+save_vars { GDBFLAGS } {
+    append GDBFLAGS " -ex \"set non-stop on\""
+    clean_restart $binfile
+}
+
+gdb_breakpoint "something"
+gdb_run_cmd
+
+# Two threads hit the bp.
+set fill "\[^\r\n\]+"
+set num_hits 0
+gdb_test_multiple "" "hit the breakpoint" -lbl {
+    -re "\r\nThread ${fill} hit Breakpoint 1${fill}" {
+	incr num_hits
+	if {$num_hits < 2} {
+	    exp_continue
+	}
+    }
+    -re "\r\n$gdb_prompt " {
+	exp_continue
+    }
+}
+gdb_assert {$num_hits == 2} "two threads hit the bp"
+
+# Count the number of running/stopped threads reported
+# by the "info threads" command.
+foreach flag {"" "-stopped"} {
+    set num_running 0
+    set num_stopped 0
+    gdb_test_multiple "info threads $flag" "info threads $flag" {
+	-re "Id${fill}Target Id${fill}Frame${fill}" {
+	    exp_continue
+	}
+	-re "^\r\n. ${decimal}${fill}Thread ${fill}.running." {
+	    incr num_running
+	    exp_continue
+	}
+	-re "^\r\n. ${decimal}${fill}Thread ${fill}something ${fill}" {
+	    incr num_stopped
+	    exp_continue
+	}
+	-re "^\r\n$gdb_prompt $" {
+	    gdb_assert {$num_stopped == 2} "$gdb_test_name: num stopped"
+	    if {$flag eq ""} {
+		gdb_assert {$num_running == 3} "$gdb_test_name: num running"
+	    } else {
+		gdb_assert {$num_running == 0} "$gdb_test_name: num running"
+	    }
+	}
+    }
+}
diff --git a/gdb/thread.c b/gdb/thread.c
index 7dc8e7018c5..87ee9f66680 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -1044,6 +1044,8 @@ struct info_threads_opts
 {
   /* For "-gid".  */
   bool show_global_ids = false;
+  /* For "-stopped".  */
+  bool show_stopped_threads = false;
 };
 
 static const gdb::option::option_def info_threads_option_defs[] = {
@@ -1053,6 +1055,11 @@ static const gdb::option::option_def info_threads_option_defs[] = {
     [] (info_threads_opts *opts) { return &opts->show_global_ids; },
     N_("Show global thread IDs."),
   },
+  gdb::option::flag_option_def<info_threads_opts> {
+    "stopped",
+    [] (info_threads_opts *opts) { return &opts->show_stopped_threads; },
+    N_("Show stopped threads only."),
+  },
 
 };
 
@@ -1095,6 +1102,11 @@ should_print_thread (const char *requested_threads, int default_inf_num,
   if (thr->state == THREAD_EXITED)
     return false;
 
+  /* Skip a running thread if the user wants stopped threads only.  */
+  bool is_stopped = (thr->state == THREAD_STOPPED);
+  if (opts.show_stopped_threads && !is_stopped)
+    return false;
+
   return true;
 }
 
@@ -1286,7 +1298,8 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
 	    if (requested_threads == NULL || *requested_threads == '\0')
 	      uiout->message (_("No threads.\n"));
 	    else
-	      uiout->message (_("No threads match '%s'.\n"),
+	      uiout->message (_("No %sthreads match '%s'.\n"),
+			      (opts.show_stopped_threads ? "stopped " : ""),
 			      requested_threads);
 	    return;
 	  }
@@ -1342,7 +1355,7 @@ void
 print_thread_info (struct ui_out *uiout, const char *requested_threads,
 		   int pid)
 {
-  info_threads_opts opts {false};
+  info_threads_opts opts {false, false};
   print_thread_info_1 (uiout, requested_threads, 1, pid, opts);
 }
 
-- 
2.34.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Sean Fennelly, Jeffrey Schneiderman, Tiffany Doon Silva
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v2 0/2] Option to show stopped threads only
  2025-03-18 18:04 ` [PATCH v2 0/2] Option to show stopped threads only Tankut Baris Aktemur
  2025-03-18 18:05   ` [PATCH v2 1/2] gdb: pass info_threads_opts to print_thread_info_1 Tankut Baris Aktemur
  2025-03-18 18:05   ` [PATCH v2 2/2] gdb: add a '-stopped' option to "info threads" Tankut Baris Aktemur
@ 2025-03-28 16:38   ` Guinevere Larsen
  2025-04-04 13:39     ` Aktemur, Tankut Baris
  2 siblings, 1 reply; 32+ messages in thread
From: Guinevere Larsen @ 2025-03-28 16:38 UTC (permalink / raw)
  To: Tankut Baris Aktemur, gdb-patches

On 3/18/25 3:04 PM, Tankut Baris Aktemur wrote:
> Hi,
>
> This is the rebased version of
>
>    https://inbox.sourceware.org/gdb-patches/cover.1680686220.git.tankut.baris.aktemur@intel.com/
>
> As a comment, Eli had expressed his view that when "info threads" is
> given a single thread ID, the "-stopped" flag could be ignored.  I
> didn't implement this yet but can gladly do that if that's the general
> preference.

Hi! Thanks for working on this!

I took a look at your patch, and I think I like how it works at this 
point. Basically, I don't like the idea of ignoring part of the input 
from the user if a different part of the input happens to look a certain 
way (in this case non-empty). Either both options should interact, or 
they should be mutually exclusive, and allowing one to take precedence 
just inserts arbitrary rules that users need to either remember or 
double check the manual every time. However, this is personal 
preference, I'm not married to either idea.

One thing that would be nice, though, would be also testing the behavior 
when a thread ID is given - whatever that behavior is. Adding a couple 
of tests calling one stopped ID, one running ID and multiple IDs, would 
essentially document to ourselves that "this is the behavior we want,it 
isn't an accident" so that if it is changed in the future, it is done so 
on purpose.

As for the patches themselves, they look good to me. I hope this gets 
reviewed soon!

Reviewed-By: Guinevere Larsen <guinevere@redhat.com>

-- 
Cheers,
Guinevere Larsen
She/Her/Hers

>
> Regards,
> Baris
>
> Tankut Baris Aktemur (2):
>    gdb: pass info_threads_opts to print_thread_info_1
>    gdb: add a '-stopped' option to "info threads"
>
>   gdb/NEWS                                      |  7 ++
>   gdb/doc/gdb.texinfo                           |  6 +-
>   gdb/testsuite/gdb.base/options.exp            | 11 ++-
>   .../gdb.threads/info-threads-stopped.c        | 78 +++++++++++++++++
>   .../gdb.threads/info-threads-stopped.exp      | 75 ++++++++++++++++
>   gdb/thread.c                                  | 86 +++++++++++--------
>   6 files changed, 226 insertions(+), 37 deletions(-)
>   create mode 100644 gdb/testsuite/gdb.threads/info-threads-stopped.c
>   create mode 100644 gdb/testsuite/gdb.threads/info-threads-stopped.exp
>


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH v3 0/2] Option to show stopped threads only
  2023-04-05  9:19 [PATCH 0/3] Option to show stopped threads only Tankut Baris Aktemur via Gdb-patches
                   ` (3 preceding siblings ...)
  2025-03-18 18:04 ` [PATCH v2 0/2] Option to show stopped threads only Tankut Baris Aktemur
@ 2025-04-04 13:36 ` Tankut Baris Aktemur
  2025-04-04 13:36   ` [PATCH v3 1/2] gdb: pass info_threads_opts to print_thread_info_1 Tankut Baris Aktemur
                     ` (4 more replies)
  4 siblings, 5 replies; 32+ messages in thread
From: Tankut Baris Aktemur @ 2025-04-04 13:36 UTC (permalink / raw)
  To: gdb-patches; +Cc: guinevere, eliz

Hi,

This is v3 of

  https://inbox.sourceware.org/gdb-patches/cover.1680686220.git.tankut.baris.aktemur@intel.com/

V2 is available at

  https://inbox.sourceware.org/gdb-patches/cover.1742320783.git.tankut.baris.aktemur@intel.com/

As a comment, Eli had expressed his view that when "info threads" is
given a single thread ID, the "-stopped" flag could be ignored.  I
didn't implement this yet but can gladly do that if that's the general
preference.  As a review, Guinevere expressed her opinion that she
prefers the submitted behavior.

Revision 3 makes the following changes:

  * Address Guinevere's comment.  That is, add new test cases that
    cover passing a single thread id, in one case a stopped thread, in
    another a running thread; and test passing two thread ids.

  * Add a trivial "print 42" to synchronize the GDB prompt.  I
    received an email notification from the Linaro CI for v2 that
    there was a test failure.  Although I could not reproduce locally,
    I believe it was caused because of the buffer contents in non-stop
    mode, which is hopefully fixed now.

  * Rebase to the current master branch.

Regards,
Baris

Tankut Baris Aktemur (2):
  gdb: pass info_threads_opts to print_thread_info_1
  gdb: add a '-stopped' option to "info threads"

 gdb/NEWS                                      |   5 +
 gdb/doc/gdb.texinfo                           |   6 +-
 gdb/testsuite/gdb.base/options.exp            |  11 +-
 .../gdb.threads/info-threads-stopped.c        |  78 +++++++++++++
 .../gdb.threads/info-threads-stopped.exp      | 107 ++++++++++++++++++
 gdb/thread.c                                  |  86 ++++++++------
 6 files changed, 256 insertions(+), 37 deletions(-)
 create mode 100644 gdb/testsuite/gdb.threads/info-threads-stopped.c
 create mode 100644 gdb/testsuite/gdb.threads/info-threads-stopped.exp

-- 
2.34.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Sean Fennelly, Jeffrey Schneiderman, Tiffany Doon Silva
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH v3 1/2] gdb: pass info_threads_opts to print_thread_info_1
  2025-04-04 13:36 ` [PATCH v3 " Tankut Baris Aktemur
@ 2025-04-04 13:36   ` Tankut Baris Aktemur
  2025-04-24 18:09     ` Pedro Alves
  2025-04-04 13:36   ` [PATCH v3 2/2] gdb: add a '-stopped' option to "info threads" Tankut Baris Aktemur
                     ` (3 subsequent siblings)
  4 siblings, 1 reply; 32+ messages in thread
From: Tankut Baris Aktemur @ 2025-04-04 13:36 UTC (permalink / raw)
  To: gdb-patches; +Cc: guinevere, eliz

The "info threads" command tracks its options in a struct named
'info_threads_opts', which currently has only one option.  Pass the
whole options object to helper functions, instead of passing
the option value individually.  This is a refactoring to make adding
more options easier.

Reviewed-By: Guinevere Larsen <guinevere@redhat.com>
---
 gdb/thread.c | 71 +++++++++++++++++++++++++++-------------------------
 1 file changed, 37 insertions(+), 34 deletions(-)

diff --git a/gdb/thread.c b/gdb/thread.c
index 8a34671bb6c..7dc8e7018c5 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -1038,6 +1038,24 @@ pc_in_thread_step_range (CORE_ADDR pc, struct thread_info *thread)
 	  && pc < thread->control.step_range_end);
 }
 
+/* The options for the "info threads" command.  */
+
+struct info_threads_opts
+{
+  /* For "-gid".  */
+  bool show_global_ids = false;
+};
+
+static const gdb::option::option_def info_threads_option_defs[] = {
+
+  gdb::option::flag_option_def<info_threads_opts> {
+    "gid",
+    [] (info_threads_opts *opts) { return &opts->show_global_ids; },
+    N_("Show global thread IDs."),
+  },
+
+};
+
 /* Helper for print_thread_info.  Returns true if THR should be
    printed.  If REQUESTED_THREADS, a list of GDB ids/ranges, is not
    NULL, only print THR if its ID is included in the list.  GLOBAL_IDS
@@ -1046,11 +1064,13 @@ pc_in_thread_step_range (CORE_ADDR pc, struct thread_info *thread)
    is a thread from the process PID.  Otherwise, threads from all
    attached PIDs are printed.  If both REQUESTED_THREADS is not NULL
    and PID is not -1, then the thread is printed if it belongs to the
-   specified process.  Otherwise, an error is raised.  */
+   specified process.  Otherwise, an error is raised.  OPTS is the
+   options of the "info threads" command.  */
 
 static bool
 should_print_thread (const char *requested_threads, int default_inf_num,
-		     int global_ids, int pid, struct thread_info *thr)
+		     int global_ids, int pid, thread_info *thr,
+		     info_threads_opts opts)
 {
   if (requested_threads != NULL && *requested_threads != '\0')
     {
@@ -1104,7 +1124,7 @@ thread_target_id_str (thread_info *tp)
 
 static void
 do_print_thread (ui_out *uiout, const char *requested_threads,
-		 int global_ids, int pid, int show_global_ids,
+		 int global_ids, int pid, info_threads_opts opts,
 		 int default_inf_num, thread_info *tp,
 		 thread_info *current_thread)
 {
@@ -1115,7 +1135,7 @@ do_print_thread (ui_out *uiout, const char *requested_threads,
     switch_to_thread (current_thread);
 
   if (!should_print_thread (requested_threads, default_inf_num,
-			    global_ids, pid, tp))
+			    global_ids, pid, tp, opts))
     return;
 
   ui_out_emit_tuple tuple_emitter (uiout, NULL);
@@ -1130,7 +1150,7 @@ do_print_thread (ui_out *uiout, const char *requested_threads,
       uiout->field_string ("id-in-tg", print_thread_id (tp));
     }
 
-  if (show_global_ids || uiout->is_mi_like_p ())
+  if (opts.show_global_ids || uiout->is_mi_like_p ())
     uiout->field_signed ("id", tp->global_num);
 
   /* Switch to the thread (and inferior / target).  */
@@ -1191,23 +1211,23 @@ do_print_thread (ui_out *uiout, const char *requested_threads,
 
 static void
 print_thread (ui_out *uiout, const char *requested_threads,
-	      int global_ids, int pid, int show_global_ids,
+	      int global_ids, int pid, info_threads_opts opts,
 	      int default_inf_num, thread_info *tp, thread_info *current_thread)
 
 {
   do_with_buffered_output (do_print_thread, uiout, requested_threads,
-			   global_ids, pid, show_global_ids,
-			   default_inf_num, tp, current_thread);
+			   global_ids, pid, opts, default_inf_num, tp,
+			   current_thread);
 }
 
 /* Like print_thread_info, but in addition, GLOBAL_IDS indicates
    whether REQUESTED_THREADS is a list of global or per-inferior
-   thread ids.  */
+   thread ids.  OPTS is the options of the "info threads" command.  */
 
 static void
 print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
 		     int global_ids, int pid,
-		     int show_global_ids)
+		     info_threads_opts opts)
 {
   int default_inf_num = current_inferior ()->num;
 
@@ -1247,7 +1267,7 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
 	      switch_to_thread (current_thread);
 
 	    if (!should_print_thread (requested_threads, default_inf_num,
-				      global_ids, pid, tp))
+				      global_ids, pid, tp, opts))
 	      continue;
 
 	    /* Switch inferiors so we're looking at the right
@@ -1271,12 +1291,12 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
 	    return;
 	  }
 
-	table_emitter.emplace (uiout, show_global_ids ? 5 : 4,
+	table_emitter.emplace (uiout, opts.show_global_ids ? 5 : 4,
 			       n_threads, "threads");
 
 	uiout->table_header (1, ui_left, "current", "");
 	uiout->table_header (4, ui_left, "id-in-tg", "Id");
-	if (show_global_ids)
+	if (opts.show_global_ids)
 	  uiout->table_header (4, ui_left, "id", "GId");
 	uiout->table_header (target_id_col_width, ui_left,
 			     "target-id", "Target Id");
@@ -1293,7 +1313,7 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
 	    current_exited = true;
 
 	  print_thread (uiout, requested_threads, global_ids, pid,
-			show_global_ids, default_inf_num, tp, current_thread);
+			opts, default_inf_num, tp, current_thread);
 	}
 
     /* This end scope restores the current thread and the frame
@@ -1322,27 +1342,10 @@ void
 print_thread_info (struct ui_out *uiout, const char *requested_threads,
 		   int pid)
 {
-  print_thread_info_1 (uiout, requested_threads, 1, pid, 0);
+  info_threads_opts opts {false};
+  print_thread_info_1 (uiout, requested_threads, 1, pid, opts);
 }
 
-/* The options for the "info threads" command.  */
-
-struct info_threads_opts
-{
-  /* For "-gid".  */
-  bool show_global_ids = false;
-};
-
-static const gdb::option::option_def info_threads_option_defs[] = {
-
-  gdb::option::flag_option_def<info_threads_opts> {
-    "gid",
-    [] (info_threads_opts *opts) { return &opts->show_global_ids; },
-    N_("Show global thread IDs."),
-  },
-
-};
-
 /* Create an option_def_group for the "info threads" options, with
    IT_OPTS as context.  */
 
@@ -1367,7 +1370,7 @@ info_threads_command (const char *arg, int from_tty)
   gdb::option::process_options
     (&arg, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, grp);
 
-  print_thread_info_1 (current_uiout, arg, 0, -1, it_opts.show_global_ids);
+  print_thread_info_1 (current_uiout, arg, 0, -1, it_opts);
 }
 
 /* Completer for the "info threads" command.  */
-- 
2.34.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Sean Fennelly, Jeffrey Schneiderman, Tiffany Doon Silva
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH v3 2/2] gdb: add a '-stopped' option to "info threads"
  2025-04-04 13:36 ` [PATCH v3 " Tankut Baris Aktemur
  2025-04-04 13:36   ` [PATCH v3 1/2] gdb: pass info_threads_opts to print_thread_info_1 Tankut Baris Aktemur
@ 2025-04-04 13:36   ` Tankut Baris Aktemur
  2025-04-24 19:23     ` Pedro Alves
  2025-04-23  8:00   ` [PATCH v3 0/2] Option to show stopped threads only Aktemur, Tankut Baris
                     ` (2 subsequent siblings)
  4 siblings, 1 reply; 32+ messages in thread
From: Tankut Baris Aktemur @ 2025-04-04 13:36 UTC (permalink / raw)
  To: gdb-patches; +Cc: guinevere, eliz

Add a '-stopped' option to the "info threads" command to print stopped
threads only and skip the running ones.  This is a convenience flag to
filter out the running threads in programs that have many threads.

Suppose we have an application with 5 threads, 2 of which have hit a
breakpoint.  The "info threads" command in the non-stop mode gives:

  (gdb) info threads
    Id   Target Id             Frame
  * 1    Thread 0x7ffff7d99740 (running)
    2    Thread 0x7ffff7d98700 something () at file.c:30
    3    Thread 0x7ffff7597700 (running)
    4    Thread 0x7ffff6d96700 something () at file.c:30
    5    Thread 0x7ffff6595700 (running)
  (gdb)

Using the "-stopped" flag, we get

  (gdb) info threads -stopped
    Id   Target Id             Frame
    2    Thread 0x7ffff7d98700 something () at file.c:30
    4    Thread 0x7ffff6d96700 something () at file.c:30
  (gdb)

When combined with a thread ID, the behavior is as follows:

  (gdb) info threads 3
    Id   Target Id             Frame
    3    Thread 0x7ffff7597700 (running)
  (gdb) info threads -stopped 3
  No stopped threads match '3'.
  (gdb)

Regression-tested on X86_64 Linux.

Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Reviewed-By: Guinevere Larsen <guinevere@redhat.com>
---
 gdb/NEWS                                      |   5 +
 gdb/doc/gdb.texinfo                           |   6 +-
 gdb/testsuite/gdb.base/options.exp            |  11 +-
 .../gdb.threads/info-threads-stopped.c        |  78 +++++++++++++
 .../gdb.threads/info-threads-stopped.exp      | 107 ++++++++++++++++++
 gdb/thread.c                                  |  17 ++-
 6 files changed, 220 insertions(+), 4 deletions(-)
 create mode 100644 gdb/testsuite/gdb.threads/info-threads-stopped.c
 create mode 100644 gdb/testsuite/gdb.threads/info-threads-stopped.exp

diff --git a/gdb/NEWS b/gdb/NEWS
index 6a557bb4af9..d5c55c3c938 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -56,6 +56,11 @@ info sharedlibrary
   command are now for the full memory range allocated to the shared
   library.
 
+info threads [-gid] [-stopped] [ID]...
+  This command now takes an optional flag, '-stopped', that causes only
+  the stopped threads to be printed.  The flag can be useful to get a
+  reduced list when there is a large number of unstopped threads.
+
 * Python API
 
   ** New class gdb.Color for dealing with colors.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index e034ac53295..3c03761dd00 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -3807,7 +3807,7 @@ Thread 1 "main" received signal SIGINT, Interrupt.
 @table @code
 @anchor{info_threads}
 @kindex info threads
-@item info threads @r{[}-gid@r{]} @r{[}@var{thread-id-list}@r{]}
+@item info threads @r{[}-gid@r{]} @r{[}-stopped@r{]} @r{[}@var{thread-id-list}@r{]}
 
 Display information about one or more threads.  With no arguments
 displays information about all threads.  You can specify the list of
@@ -3857,6 +3857,10 @@ If you're debugging multiple inferiors, @value{GDBN} displays thread
 IDs using the qualified @var{inferior-num}.@var{thread-num} format.
 Otherwise, only @var{thread-num} is shown.
 
+If you specify the @samp{-stopped} option, @value{GDBN} displays the
+stopped threads only.  This can be helpful to reduce the output list
+if there is a large number of unstopped threads.
+
 If you specify the @samp{-gid} option, @value{GDBN} displays a column
 indicating each thread's global thread ID:
 
diff --git a/gdb/testsuite/gdb.base/options.exp b/gdb/testsuite/gdb.base/options.exp
index 8760a918082..90902e94086 100644
--- a/gdb/testsuite/gdb.base/options.exp
+++ b/gdb/testsuite/gdb.base/options.exp
@@ -509,12 +509,21 @@ proc_with_prefix test-thread-apply {} {
 proc_with_prefix test-info-threads {} {
     test_gdb_complete_multiple "info threads " "" "" {
 	"-gid"
+	"-stopped"
 	"ID"
     }
 
+    test_gdb_complete_multiple "info threads " "-" "" {
+	"-gid"
+	"-stopped"
+    }
+
     test_gdb_complete_unique \
-	"info threads -" \
+	"info threads -g" \
 	"info threads -gid"
+    test_gdb_complete_unique \
+	"info threads -s" \
+	"info threads -stopped"
 
     # "ID" isn't really something the user can type.
     test_gdb_complete_none "info threads I"
diff --git a/gdb/testsuite/gdb.threads/info-threads-stopped.c b/gdb/testsuite/gdb.threads/info-threads-stopped.c
new file mode 100644
index 00000000000..2c38ecca074
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/info-threads-stopped.c
@@ -0,0 +1,78 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2022-2025 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#define NUM 4
+
+volatile int should_spin = 1;
+
+static void
+something ()
+{
+}
+
+static void
+spin ()
+{
+  while (should_spin)
+    usleep (1);
+}
+
+static void *
+work (void *arg)
+{
+  int id = *((int *) arg);
+
+  /* Sleep a bit to give the other threads a chance to run.  */
+  usleep (1);
+
+  if (id % 2 == 0)
+    something (); /* break-here */
+  else
+    spin ();
+
+  pthread_exit (NULL);
+}
+
+int
+main ()
+{
+  /* Ensure we stop if GDB crashes and DejaGNU fails to kill us.  */
+  alarm (10);
+
+  pthread_t threads[NUM];
+  void *thread_result;
+  int ids[NUM];
+
+  for (int i = 0; i < NUM; i++)
+    {
+      ids[i] = i + 2;
+      pthread_create (&threads[i], NULL, work, &(ids[i]));
+    }
+
+  sleep (10);
+  should_spin = 0;
+
+  for (int i = 0; i < NUM; i++)
+    pthread_join(threads[i], &thread_result);
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.threads/info-threads-stopped.exp b/gdb/testsuite/gdb.threads/info-threads-stopped.exp
new file mode 100644
index 00000000000..37d6622697c
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/info-threads-stopped.exp
@@ -0,0 +1,107 @@
+# Copyright (C) 2022-2025 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test for the '-stopped' flag of the "info threads" command.
+
+standard_testfile
+
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
+	 executable debug] != "" } {
+    return -1
+}
+
+save_vars { GDBFLAGS } {
+    append GDBFLAGS " -ex \"set non-stop on\""
+    clean_restart $binfile
+}
+
+gdb_breakpoint "something"
+gdb_run_cmd
+
+# Two threads hit the bp.
+set fill "\[^\r\n\]+"
+set num_hits 0
+gdb_test_multiple "" "hit the breakpoint" -lbl {
+    -re "\r\nThread ${fill} hit Breakpoint 1${fill}" {
+	incr num_hits
+	if {$num_hits < 2} {
+	    exp_continue
+	}
+    }
+    -re "\r\n$gdb_prompt " {
+	exp_continue
+    }
+}
+gdb_assert {$num_hits == 2} "two threads hit the bp"
+
+# We are in non-stop mode.
+# Send a simple command to resync the command prompt.
+gdb_test "p 42" " = 42"
+
+# Count the number of running/stopped threads reported
+# by the "info threads" command.  We also capture thread ids
+# for additional tests.
+set running_tid "invalid"
+set stopped_tid "invalid"
+
+foreach flag {"" "-stopped"} {
+    set num_running 0
+    set num_stopped 0
+    gdb_test_multiple "info threads $flag" "info threads $flag" {
+	-re "Id${fill}Target Id${fill}Frame${fill}" {
+	    exp_continue
+	}
+	-re "^\r\n. (${decimal})${fill}Thread ${fill}.running." {
+	    incr num_running
+	    set running_tid $expect_out(1,string)
+	    exp_continue
+	}
+	-re "^\r\n. (${decimal})${fill}Thread ${fill}something ${fill}${srcfile}:${decimal}" {
+	    incr num_stopped
+	    set stopped_tid $expect_out(1,string)
+	    exp_continue
+	}
+	-re "^\r\n$gdb_prompt $" {
+	    gdb_assert {$num_stopped == 2} "$gdb_test_name: num stopped"
+	    if {$flag eq ""} {
+		gdb_assert {$num_running == 3} "$gdb_test_name: num running"
+	    } else {
+		gdb_assert {$num_running == 0} "$gdb_test_name: num running"
+	    }
+	}
+    }
+}
+
+gdb_assert {$running_tid != "invalid"} "found a running thread"
+gdb_assert {$stopped_tid != "invalid"} "found a stopped thread"
+
+# Test specifying thread ids.
+gdb_test "info threads -stopped $running_tid" \
+    "No stopped threads match '$running_tid'\." \
+    "info thread -stopped for a running thread"
+
+set fill "\[^\r\n\]+"
+set ws "\[ \t\]+"
+gdb_test "info threads -stopped $stopped_tid" \
+    [multi_line \
+	 "${ws}Id${ws}Target Id${ws}Frame${ws}" \
+	 "${ws}${stopped_tid}${ws}Thread ${fill} something ${fill}"] \
+    "info thread -stopped for a stopped thread"
+
+gdb_test "info threads -stopped $running_tid $stopped_tid" \
+    [multi_line \
+	 "${ws}Id${ws}Target Id${ws}Frame${ws}" \
+	 "${ws}${stopped_tid}${ws}Thread ${fill} something ${fill}"] \
+    "info thread -stopped for a running and a stopped thread"
diff --git a/gdb/thread.c b/gdb/thread.c
index 7dc8e7018c5..87ee9f66680 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -1044,6 +1044,8 @@ struct info_threads_opts
 {
   /* For "-gid".  */
   bool show_global_ids = false;
+  /* For "-stopped".  */
+  bool show_stopped_threads = false;
 };
 
 static const gdb::option::option_def info_threads_option_defs[] = {
@@ -1053,6 +1055,11 @@ static const gdb::option::option_def info_threads_option_defs[] = {
     [] (info_threads_opts *opts) { return &opts->show_global_ids; },
     N_("Show global thread IDs."),
   },
+  gdb::option::flag_option_def<info_threads_opts> {
+    "stopped",
+    [] (info_threads_opts *opts) { return &opts->show_stopped_threads; },
+    N_("Show stopped threads only."),
+  },
 
 };
 
@@ -1095,6 +1102,11 @@ should_print_thread (const char *requested_threads, int default_inf_num,
   if (thr->state == THREAD_EXITED)
     return false;
 
+  /* Skip a running thread if the user wants stopped threads only.  */
+  bool is_stopped = (thr->state == THREAD_STOPPED);
+  if (opts.show_stopped_threads && !is_stopped)
+    return false;
+
   return true;
 }
 
@@ -1286,7 +1298,8 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
 	    if (requested_threads == NULL || *requested_threads == '\0')
 	      uiout->message (_("No threads.\n"));
 	    else
-	      uiout->message (_("No threads match '%s'.\n"),
+	      uiout->message (_("No %sthreads match '%s'.\n"),
+			      (opts.show_stopped_threads ? "stopped " : ""),
 			      requested_threads);
 	    return;
 	  }
@@ -1342,7 +1355,7 @@ void
 print_thread_info (struct ui_out *uiout, const char *requested_threads,
 		   int pid)
 {
-  info_threads_opts opts {false};
+  info_threads_opts opts {false, false};
   print_thread_info_1 (uiout, requested_threads, 1, pid, opts);
 }
 
-- 
2.34.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Sean Fennelly, Jeffrey Schneiderman, Tiffany Doon Silva
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 32+ messages in thread

* RE: [PATCH v2 0/2] Option to show stopped threads only
  2025-03-28 16:38   ` [PATCH v2 0/2] Option to show stopped threads only Guinevere Larsen
@ 2025-04-04 13:39     ` Aktemur, Tankut Baris
  0 siblings, 0 replies; 32+ messages in thread
From: Aktemur, Tankut Baris @ 2025-04-04 13:39 UTC (permalink / raw)
  To: Guinevere Larsen, gdb-patches

On Friday, March 28, 2025 5:38 PM, Guinevere Larsen wrote:
> On 3/18/25 3:04 PM, Tankut Baris Aktemur wrote:
> > Hi,
> >
> > This is the rebased version of
> >
> >    https://inbox.sourceware.org/gdb-
> patches/cover.1680686220.git.tankut.baris.aktemur@intel.com/
> >
> > As a comment, Eli had expressed his view that when "info threads" is
> > given a single thread ID, the "-stopped" flag could be ignored.  I
> > didn't implement this yet but can gladly do that if that's the general
> > preference.
> 
> Hi! Thanks for working on this!
> 
> I took a look at your patch, and I think I like how it works at this
> point. Basically, I don't like the idea of ignoring part of the input
> from the user if a different part of the input happens to look a certain
> way (in this case non-empty). Either both options should interact, or
> they should be mutually exclusive, and allowing one to take precedence
> just inserts arbitrary rules that users need to either remember or
> double check the manual every time. However, this is personal
> preference, I'm not married to either idea.
> 
> One thing that would be nice, though, would be also testing the behavior
> when a thread ID is given - whatever that behavior is. Adding a couple
> of tests calling one stopped ID, one running ID and multiple IDs, would
> essentially document to ourselves that "this is the behavior we want,it
> isn't an accident" so that if it is changed in the future, it is done so
> on purpose.
> 
> As for the patches themselves, they look good to me. I hope this gets
> reviewed soon!
> 
> Reviewed-By: Guinevere Larsen <guinevere@redhat.com>

Thank you for your review and comments.  I added the new test cases and submitted v3.

Regards
-Baris


Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Sean Fennelly, Jeffrey Schneiderman, Tiffany Doon Silva
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928

^ permalink raw reply	[flat|nested] 32+ messages in thread

* RE: [PATCH v3 0/2] Option to show stopped threads only
  2025-04-04 13:36 ` [PATCH v3 " Tankut Baris Aktemur
  2025-04-04 13:36   ` [PATCH v3 1/2] gdb: pass info_threads_opts to print_thread_info_1 Tankut Baris Aktemur
  2025-04-04 13:36   ` [PATCH v3 2/2] gdb: add a '-stopped' option to "info threads" Tankut Baris Aktemur
@ 2025-04-23  8:00   ` Aktemur, Tankut Baris
  2025-04-24 17:53   ` Pedro Alves
  2025-05-05 16:19   ` [PATCH v4 0/3] Option to show stopped/running " Tankut Baris Aktemur
  4 siblings, 0 replies; 32+ messages in thread
From: Aktemur, Tankut Baris @ 2025-04-23  8:00 UTC (permalink / raw)
  To: gdb-patches; +Cc: guinevere, eliz

Kindly pinging.

Thanks,
-Baris

On Friday, April 4, 2025 3:37 PM, Aktemur, Tankut Baris wrote:
> Hi,
> 
> This is v3 of
> 
>   https://inbox.sourceware.org/gdb-
> patches/cover.1680686220.git.tankut.baris.aktemur@intel.com/
> 
> V2 is available at
> 
>   https://inbox.sourceware.org/gdb-
> patches/cover.1742320783.git.tankut.baris.aktemur@intel.com/
> 
> As a comment, Eli had expressed his view that when "info threads" is
> given a single thread ID, the "-stopped" flag could be ignored.  I
> didn't implement this yet but can gladly do that if that's the general
> preference.  As a review, Guinevere expressed her opinion that she
> prefers the submitted behavior.
> 
> Revision 3 makes the following changes:
> 
>   * Address Guinevere's comment.  That is, add new test cases that
>     cover passing a single thread id, in one case a stopped thread, in
>     another a running thread; and test passing two thread ids.
> 
>   * Add a trivial "print 42" to synchronize the GDB prompt.  I
>     received an email notification from the Linaro CI for v2 that
>     there was a test failure.  Although I could not reproduce locally,
>     I believe it was caused because of the buffer contents in non-stop
>     mode, which is hopefully fixed now.
> 
>   * Rebase to the current master branch.
> 
> Regards,
> Baris
> 
> Tankut Baris Aktemur (2):
>   gdb: pass info_threads_opts to print_thread_info_1
>   gdb: add a '-stopped' option to "info threads"
> 
>  gdb/NEWS                                      |   5 +
>  gdb/doc/gdb.texinfo                           |   6 +-
>  gdb/testsuite/gdb.base/options.exp            |  11 +-
>  .../gdb.threads/info-threads-stopped.c        |  78 +++++++++++++
>  .../gdb.threads/info-threads-stopped.exp      | 107 ++++++++++++++++++
>  gdb/thread.c                                  |  86 ++++++++------
>  6 files changed, 256 insertions(+), 37 deletions(-)
>  create mode 100644 gdb/testsuite/gdb.threads/info-threads-stopped.c
>  create mode 100644 gdb/testsuite/gdb.threads/info-threads-stopped.exp
> 
> --
> 2.34.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Sean Fennelly, Jeffrey Schneiderman, Tiffany Doon Silva
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 3/3] gdb: add a '-stopped' option to "info threads"
  2023-04-05 11:31         ` Aktemur, Tankut Baris via Gdb-patches
  2023-04-05 11:56           ` Eli Zaretskii via Gdb-patches
@ 2025-04-24 14:50           ` Pedro Alves
  1 sibling, 0 replies; 32+ messages in thread
From: Pedro Alves @ 2025-04-24 14:50 UTC (permalink / raw)
  To: Aktemur, Tankut Baris, Eli Zaretskii, gdb-patches

Hi!

On 2023-04-05 12:31, Aktemur, Tankut Baris via Gdb-patches wrote:
> On Wednesday, April 5, 2023 12:51 PM, Eli Zaretskii wrote:
>>> From: "Aktemur, Tankut Baris" <tankut.baris.aktemur@intel.com>
>>> Date: Wed, 5 Apr 2023 10:19:26 +0000
>>>
>>> I'm fine if we make the single thread id a special case.
>>
>> Maybe that's all we should do.
>>
>>> But then the question is, where do we draw the line?  If the user
>>> gave just a few thread ids, do we still ignore the flag?  What is
>>> the limit to the acceptable list length?  Because of these
>>> questions, consistently applying the flag made more sense to me.
>>
>> We don't have to be 100% consistent, we just need to be useful.
> 
> Let's please wait a bit in case other maintainers want to chime in.
> I don't have an objection to treating the single thread id case specially.

I don't think we should give single ID any special treatment.  It's as you say,
what about "info thread 1 2 ", does that get an exception because it
is two single IDs?  Why would that be different from "info threads 1-2" ?
What if I put the IDs in a convenience variable, and then do:

 (gdb) eval "info threads -stopped %s", $id

Why should my script behave differently depending on what is saved in $id?

Etc.

BTW, the same rationale should apply to "thread apply".  "info threads" and "thread apply"
have basically the same logic and also share options.  IMO, we should have a matching "thread apply -stopped" too.

And with "thread apply", it is even clearer IMO that "thread apply $ID -stopped print foo" should not
every try to run "print foo" on a not-stopped thread!  From the fact that "info threads" and "thread apply"
should walk the same threads given the same options, it follows that "info threads -stopped" should not walk
any non-stopped thread.

I'll look at later revisions of the series now.  Thanks for doing this.  We had talked about it a while ago but
I hadn't realized you had sent it upstream.  Thanks!

Pedro Alves


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v3 0/2] Option to show stopped threads only
  2025-04-04 13:36 ` [PATCH v3 " Tankut Baris Aktemur
                     ` (2 preceding siblings ...)
  2025-04-23  8:00   ` [PATCH v3 0/2] Option to show stopped threads only Aktemur, Tankut Baris
@ 2025-04-24 17:53   ` Pedro Alves
  2025-05-05 16:19   ` [PATCH v4 0/3] Option to show stopped/running " Tankut Baris Aktemur
  4 siblings, 0 replies; 32+ messages in thread
From: Pedro Alves @ 2025-04-24 17:53 UTC (permalink / raw)
  To: Tankut Baris Aktemur, gdb-patches; +Cc: guinevere, eliz

Hi Baris,

On 2025-04-04 14:36, Tankut Baris Aktemur wrote:

> Revision 3 makes the following changes:

...

> 
>   * Add a trivial "print 42" to synchronize the GDB prompt.  I
>     received an email notification from the Linaro CI for v2 that
>     there was a test failure.  Although I could not reproduce locally,
>     I believe it was caused because of the buffer contents in non-stop
>     mode, which is hopefully fixed now.

This usually means something is off in the test, not matching expect output
with gdb_test_multiple completely correctly, or some $gdb_prompt mishandling.  I'll see if
I can fix it for you.  Stay tuned.

Pedro Alves


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v3 1/2] gdb: pass info_threads_opts to print_thread_info_1
  2025-04-04 13:36   ` [PATCH v3 1/2] gdb: pass info_threads_opts to print_thread_info_1 Tankut Baris Aktemur
@ 2025-04-24 18:09     ` Pedro Alves
  0 siblings, 0 replies; 32+ messages in thread
From: Pedro Alves @ 2025-04-24 18:09 UTC (permalink / raw)
  To: Tankut Baris Aktemur, gdb-patches; +Cc: guinevere, eliz

On 2025-04-04 14:36, Tankut Baris Aktemur wrote:

>  /* Helper for print_thread_info.  Returns true if THR should be
>     printed.  If REQUESTED_THREADS, a list of GDB ids/ranges, is not
>     NULL, only print THR if its ID is included in the list.  GLOBAL_IDS
> @@ -1046,11 +1064,13 @@ pc_in_thread_step_range (CORE_ADDR pc, struct thread_info *thread)
>     is a thread from the process PID.  Otherwise, threads from all
>     attached PIDs are printed.  If both REQUESTED_THREADS is not NULL
>     and PID is not -1, then the thread is printed if it belongs to the
> -   specified process.  Otherwise, an error is raised.  */
> +   specified process.  Otherwise, an error is raised.  OPTS is the
> +   options of the "info threads" command.  */
>  
>  static bool
>  should_print_thread (const char *requested_threads, int default_inf_num,
> -		     int global_ids, int pid, struct thread_info *thr)
> +		     int global_ids, int pid, thread_info *thr,
> +		     info_threads_opts opts)

Would you mind making that argument be the one after "requested_threads"?  I.e.,
make it the second argument.  That is so that both user-input arguments are next to
one another.  And make it a const ref, as this structure will grow
other fields and become larger.  I.e., write:

static bool
should_print_thread (const char *requested_threads, 
                     const info_threads_opts &opts,
                     int default_inf_num,
                     ...

Same logic for the other functions.

>      /* This end scope restores the current thread and the frame
> @@ -1322,27 +1342,10 @@ void
>  print_thread_info (struct ui_out *uiout, const char *requested_threads,
>  		   int pid)
>  {
> -  print_thread_info_1 (uiout, requested_threads, 1, pid, 0);
> +  info_threads_opts opts {false};

This can be just:

   info_threads_opts opts;

as the boolean field has an in-class initializer.

With that it LGTM.

Pedro Alves


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v3 2/2] gdb: add a '-stopped' option to "info threads"
  2025-04-04 13:36   ` [PATCH v3 2/2] gdb: add a '-stopped' option to "info threads" Tankut Baris Aktemur
@ 2025-04-24 19:23     ` Pedro Alves
  2025-05-05 16:17       ` Aktemur, Tankut Baris
  0 siblings, 1 reply; 32+ messages in thread
From: Pedro Alves @ 2025-04-24 19:23 UTC (permalink / raw)
  To: Tankut Baris Aktemur, gdb-patches; +Cc: guinevere, eliz

[-- Attachment #1: Type: text/plain, Size: 15052 bytes --]

Hi!

On 2025-04-04 14:36, Tankut Baris Aktemur wrote:
> Add a '-stopped' option to the "info threads" command to print stopped
> threads only and skip the running ones.  This is a convenience flag to
> filter out the running threads in programs that have many threads.
> 
> Suppose we have an application with 5 threads, 2 of which have hit a
> breakpoint.  The "info threads" command in the non-stop mode gives:
> 
>   (gdb) info threads
>     Id   Target Id             Frame
>   * 1    Thread 0x7ffff7d99740 (running)
>     2    Thread 0x7ffff7d98700 something () at file.c:30
>     3    Thread 0x7ffff7597700 (running)
>     4    Thread 0x7ffff6d96700 something () at file.c:30
>     5    Thread 0x7ffff6595700 (running)
>   (gdb)
> 
> Using the "-stopped" flag, we get
> 
>   (gdb) info threads -stopped
>     Id   Target Id             Frame
>     2    Thread 0x7ffff7d98700 something () at file.c:30
>     4    Thread 0x7ffff6d96700 something () at file.c:30
>   (gdb)
> 
> When combined with a thread ID, the behavior is as follows:
> 
>   (gdb) info threads 3
>     Id   Target Id             Frame
>     3    Thread 0x7ffff7597700 (running)
>   (gdb) info threads -stopped 3
>   No stopped threads match '3'.
>   (gdb)
> 
> Regression-tested on X86_64 Linux.
> 
> Reviewed-By: Eli Zaretskii <eliz@gnu.org>
> Reviewed-By: Guinevere Larsen <guinevere@redhat.com>
> ---
>  gdb/NEWS                                      |   5 +
>  gdb/doc/gdb.texinfo                           |   6 +-
>  gdb/testsuite/gdb.base/options.exp            |  11 +-
>  .../gdb.threads/info-threads-stopped.c        |  78 +++++++++++++
>  .../gdb.threads/info-threads-stopped.exp      | 107 ++++++++++++++++++
>  gdb/thread.c                                  |  17 ++-
>  6 files changed, 220 insertions(+), 4 deletions(-)
>  create mode 100644 gdb/testsuite/gdb.threads/info-threads-stopped.c
>  create mode 100644 gdb/testsuite/gdb.threads/info-threads-stopped.exp
> 
> diff --git a/gdb/NEWS b/gdb/NEWS
> index 6a557bb4af9..d5c55c3c938 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -56,6 +56,11 @@ info sharedlibrary
>    command are now for the full memory range allocated to the shared
>    library.
>  
> +info threads [-gid] [-stopped] [ID]...
> +  This command now takes an optional flag, '-stopped', that causes only
> +  the stopped threads to be printed.  The flag can be useful to get a
> +  reduced list when there is a large number of unstopped threads.


Cool!

(I would have added -running too while at it, and make "thread apply -stopped" work too.

 And then:

  "info threads -stopped -running"

 would print both stopped and running.

 Same logic as "info lanes -active -inactive" including both active and inactive in
 our offlist discussions.)

> +
>  * Python API
>  
>    ** New class gdb.Color for dealing with colors.
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index e034ac53295..3c03761dd00 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -3807,7 +3807,7 @@ Thread 1 "main" received signal SIGINT, Interrupt.
>  @table @code
>  @anchor{info_threads}
>  @kindex info threads
> -@item info threads @r{[}-gid@r{]} @r{[}@var{thread-id-list}@r{]}
> +@item info threads @r{[}-gid@r{]} @r{[}-stopped@r{]} @r{[}@var{thread-id-list}@r{]}
>  
>  Display information about one or more threads.  With no arguments
>  displays information about all threads.  You can specify the list of
> @@ -3857,6 +3857,10 @@ If you're debugging multiple inferiors, @value{GDBN} displays thread
>  IDs using the qualified @var{inferior-num}.@var{thread-num} format.
>  Otherwise, only @var{thread-num} is shown.
>  
> +If you specify the @samp{-stopped} option, @value{GDBN} displays the
> +stopped threads only.  This can be helpful to reduce the output list
> +if there is a large number of unstopped threads.
> +
>  If you specify the @samp{-gid} option, @value{GDBN} displays a column
>  indicating each thread's global thread ID:
>  
> diff --git a/gdb/testsuite/gdb.base/options.exp b/gdb/testsuite/gdb.base/options.exp
> index 8760a918082..90902e94086 100644
> --- a/gdb/testsuite/gdb.base/options.exp
> +++ b/gdb/testsuite/gdb.base/options.exp
> @@ -509,12 +509,21 @@ proc_with_prefix test-thread-apply {} {
>  proc_with_prefix test-info-threads {} {
>      test_gdb_complete_multiple "info threads " "" "" {
>  	"-gid"
> +	"-stopped"
>  	"ID"
>      }
>  
> +    test_gdb_complete_multiple "info threads " "-" "" {
> +	"-gid"
> +	"-stopped"
> +    }
> +
>      test_gdb_complete_unique \
> -	"info threads -" \
> +	"info threads -g" \
>  	"info threads -gid"
> +    test_gdb_complete_unique \
> +	"info threads -s" \
> +	"info threads -stopped"
>  
>      # "ID" isn't really something the user can type.
>      test_gdb_complete_none "info threads I"
> diff --git a/gdb/testsuite/gdb.threads/info-threads-stopped.c b/gdb/testsuite/gdb.threads/info-threads-stopped.c
> new file mode 100644
> index 00000000000..2c38ecca074
> --- /dev/null
> +++ b/gdb/testsuite/gdb.threads/info-threads-stopped.c
> @@ -0,0 +1,78 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2022-2025 Free Software Foundation, Inc.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +#include <stdio.h>
> +#include <unistd.h>
> +#include <stdlib.h>
> +#include <pthread.h>
> +
> +#define NUM 4
> +
> +volatile int should_spin = 1;
> +
> +static void
> +something ()
> +{
> +}
> +
> +static void
> +spin ()
> +{
> +  while (should_spin)
> +    usleep (1);
> +}
> +
> +static void *
> +work (void *arg)
> +{
> +  int id = *((int *) arg);
> +
> +  /* Sleep a bit to give the other threads a chance to run.  */
> +  usleep (1);

This usleep isn't in a loop, so why is it needed?

> +
> +  if (id % 2 == 0)
> +    something (); /* break-here */
> +  else
> +    spin ();
> +
> +  pthread_exit (NULL);
> +}
> +
> +int
> +main ()
> +{
> +  /* Ensure we stop if GDB crashes and DejaGNU fails to kill us.  */
> +  alarm (10);

This is 10 seconds ...

> +
> +  pthread_t threads[NUM];
> +  void *thread_result;
> +  int ids[NUM];
> +
> +  for (int i = 0; i < NUM; i++)
> +    {
> +      ids[i] = i + 2;
> +      pthread_create (&threads[i], NULL, work, &(ids[i]));
> +    }
> +
> +  sleep (10);

... and this is 10 seconds too.  Shouldn't the alarm clock be larger to give it a chance of clean exit?

Actually better is to not have a timer at all.  We can do that with a barrier that guarantees that
we reach a breakpoint only after all threads have been seen.  That fixes an issue which is that the
test is expecting to hit two breakpoints, but it isn't waiting until the threads that are not supposed
to hit a breakpoint actually start!  Due to scheduling, you could end up doing "info threads" before all
those threads are seen by GDB.  Using a barrier fixes that.

> +  should_spin = 0;
> +
> +  for (int i = 0; i < NUM; i++)
> +    pthread_join(threads[i], &thread_result);

Space missing: "pthread_join (".

You are not using thread_result for anything, so that could be:

    pthread_join (threads[i], NULL);

But really, with a barrier and given the alarm, this is dead code, basically.  Since we need a breakpoint after
the barrier, might as well make the main thread hit the something() breakpoint too and be considered a stopped thread.

(See attached patch.)

> +
> +  return 0;
> +}
> diff --git a/gdb/testsuite/gdb.threads/info-threads-stopped.exp b/gdb/testsuite/gdb.threads/info-threads-stopped.exp
> new file mode 100644
> index 00000000000..37d6622697c
> --- /dev/null
> +++ b/gdb/testsuite/gdb.threads/info-threads-stopped.exp
> @@ -0,0 +1,107 @@
> +# Copyright (C) 2022-2025 Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <http://www.gnu.org/licenses/>.
> +
> +# Test for the '-stopped' flag of the "info threads" command.
> +
> +standard_testfile
> +
> +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
> +	 executable debug] != "" } {
> +    return -1
> +}
> +
> +save_vars { GDBFLAGS } {
> +    append GDBFLAGS " -ex \"set non-stop on\""
> +    clean_restart $binfile
> +}
> +
> +gdb_breakpoint "something"
> +gdb_run_cmd
> +
> +# Two threads hit the bp.
> +set fill "\[^\r\n\]+"
> +set num_hits 0
> +gdb_test_multiple "" "hit the breakpoint" -lbl {
> +    -re "\r\nThread ${fill} hit Breakpoint 1${fill}" {
> +	incr num_hits
> +	if {$num_hits < 2} {
> +	    exp_continue
> +	}
> +    }
> +    -re "\r\n$gdb_prompt " {
> +	exp_continue
> +    }
> +}

It's better to write this in a way that explicitly always consumes the prompt.

> +gdb_assert {$num_hits == 2} "two threads hit the bp"
> +
> +# We are in non-stop mode.
> +# Send a simple command to resync the command prompt.
> +gdb_test "p 42" " = 42"

Then this shouldn't be needed.

> +
> +# Count the number of running/stopped threads reported
> +# by the "info threads" command.  We also capture thread ids
> +# for additional tests.
> +set running_tid "invalid"
> +set stopped_tid "invalid"
> +
> +foreach flag {"" "-stopped"} {
> +    set num_running 0
> +    set num_stopped 0
> +    gdb_test_multiple "info threads $flag" "info threads $flag" {
> +	-re "Id${fill}Target Id${fill}Frame${fill}" {
> +	    exp_continue
> +	}
> +	-re "^\r\n. (${decimal})${fill}Thread ${fill}.running." {
> +	    incr num_running
> +	    set running_tid $expect_out(1,string)
> +	    exp_continue
> +	}
> +	-re "^\r\n. (${decimal})${fill}Thread ${fill}something ${fill}${srcfile}:${decimal}" {
> +	    incr num_stopped
> +	    set stopped_tid $expect_out(1,string)
> +	    exp_continue
> +	}
> +	-re "^\r\n$gdb_prompt $" {
> +	    gdb_assert {$num_stopped == 2} "$gdb_test_name: num stopped"
> +	    if {$flag eq ""} {
> +		gdb_assert {$num_running == 3} "$gdb_test_name: num running"
> +	    } else {
> +		gdb_assert {$num_running == 0} "$gdb_test_name: num running"

It's better practice have the same number of PASSes and FAILs.  They won't match if the prompt
regexp doesn't match.

> +	    }
> +	}
> +    }

This needs some fixing around regexp matching.  It is currently racy wrt to how much expect happens to
manage to read into in the expect buffer at a time.  If you run the test with "make check-read1" to force
one byte at a time, it exposes the races reliably:

 $ make check-read1 TESTS="gdb.threads/info-threads-stopped.exp"
 ...
 FAIL: gdb.threads/info-threads-stopped.exp: info threads
 FAIL: gdb.threads/info-threads-stopped.exp: info threads -stopped
 
                 === gdb Summary ===
 
 # of expected passes            8
 # of unexpected failures        2

I've attached a patch that fixes all the testcase issues that you can squash into yours.


> +}
> +
> +gdb_assert {$running_tid != "invalid"} "found a running thread"
> +gdb_assert {$stopped_tid != "invalid"} "found a stopped thread"
> +
> +# Test specifying thread ids.
> +gdb_test "info threads -stopped $running_tid" \
> +    "No stopped threads match '$running_tid'\." \
> +    "info thread -stopped for a running thread"
> +
> +set fill "\[^\r\n\]+"
> +set ws "\[ \t\]+"
> +gdb_test "info threads -stopped $stopped_tid" \
> +    [multi_line \
> +	 "${ws}Id${ws}Target Id${ws}Frame${ws}" \
> +	 "${ws}${stopped_tid}${ws}Thread ${fill} something ${fill}"] \
> +    "info thread -stopped for a stopped thread"
> +
> +gdb_test "info threads -stopped $running_tid $stopped_tid" \
> +    [multi_line \
> +	 "${ws}Id${ws}Target Id${ws}Frame${ws}" \
> +	 "${ws}${stopped_tid}${ws}Thread ${fill} something ${fill}"] \
> +    "info thread -stopped for a running and a stopped thread"
> diff --git a/gdb/thread.c b/gdb/thread.c
> index 7dc8e7018c5..87ee9f66680 100644
> --- a/gdb/thread.c
> +++ b/gdb/thread.c
> @@ -1044,6 +1044,8 @@ struct info_threads_opts
>  {
>    /* For "-gid".  */
>    bool show_global_ids = false;
> +  /* For "-stopped".  */
> +  bool show_stopped_threads = false;
>  };
>  
>  static const gdb::option::option_def info_threads_option_defs[] = {
> @@ -1053,6 +1055,11 @@ static const gdb::option::option_def info_threads_option_defs[] = {
>      [] (info_threads_opts *opts) { return &opts->show_global_ids; },
>      N_("Show global thread IDs."),
>    },
> +  gdb::option::flag_option_def<info_threads_opts> {
> +    "stopped",
> +    [] (info_threads_opts *opts) { return &opts->show_stopped_threads; },
> +    N_("Show stopped threads only."),
> +  },
>  
>  };
>  
> @@ -1095,6 +1102,11 @@ should_print_thread (const char *requested_threads, int default_inf_num,
>    if (thr->state == THREAD_EXITED)
>      return false;
>  
> +  /* Skip a running thread if the user wants stopped threads only.  */
> +  bool is_stopped = (thr->state == THREAD_STOPPED);
> +  if (opts.show_stopped_threads && !is_stopped)
> +    return false;
> +
>    return true;
>  }
>  
> @@ -1286,7 +1298,8 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
>  	    if (requested_threads == NULL || *requested_threads == '\0')
>  	      uiout->message (_("No threads.\n"));
>  	    else
> -	      uiout->message (_("No threads match '%s'.\n"),
> +	      uiout->message (_("No %sthreads match '%s'.\n"),
> +			      (opts.show_stopped_threads ? "stopped " : ""),
>  			      requested_threads);

I don't think we should do this.  For one, it's not i18n friendly how that is written.

Then, once we add a filter like "-running" too, then it'll get awkward with:

  (gdb) info threads -stopped -running
  *what would we say here?*

I think the easiest is to just drop the %s part, and just say that no threads matched, like:

  	    if (!any_threads)
  	      uiout->message (_("No threads.\n"));
            else
	      uiout->message (_("No threads matched.\n"));

I've also attached a attached patch for this to make it easier to see what I mean.

Note that "\." in your regexp does not match a period.  It needs to be two back slashes "\\." as in my patch.

Thanks,
Pedro Alves

[-- Attachment #2: 0001-Fix-test-races.patch --]
[-- Type: text/x-patch, Size: 5764 bytes --]

From f895c8244f61a24d7d8661a033324706940bfef5 Mon Sep 17 00:00:00 2001
From: Pedro Alves <pedro@palves.net>
Date: Thu, 24 Apr 2025 20:09:16 +0100
Subject: [PATCH 1/2] Fix test races

Change-Id: Ia98a3195282a82fc68104f61cba1216bf0a296a0
---
 .../gdb.threads/info-threads-stopped.c        | 27 +++++----
 .../gdb.threads/info-threads-stopped.exp      | 56 ++++++++++---------
 2 files changed, 42 insertions(+), 41 deletions(-)

diff --git a/gdb/testsuite/gdb.threads/info-threads-stopped.c b/gdb/testsuite/gdb.threads/info-threads-stopped.c
index 2c38ecca074..2c4cd854bb7 100644
--- a/gdb/testsuite/gdb.threads/info-threads-stopped.c
+++ b/gdb/testsuite/gdb.threads/info-threads-stopped.c
@@ -22,30 +22,29 @@
 
 #define NUM 4
 
-volatile int should_spin = 1;
+static pthread_barrier_t threads_started_barrier;
 
 static void
-something ()
+stop_here ()
 {
 }
 
 static void
 spin ()
 {
-  while (should_spin)
+  while (1)
     usleep (1);
 }
 
 static void *
 work (void *arg)
 {
-  int id = *((int *) arg);
+  int id = *(int *) arg;
 
-  /* Sleep a bit to give the other threads a chance to run.  */
-  usleep (1);
+  pthread_barrier_wait (&threads_started_barrier);
 
   if (id % 2 == 0)
-    something (); /* break-here */
+    stop_here ();
   else
     spin ();
 
@@ -59,20 +58,20 @@ main ()
   alarm (10);
 
   pthread_t threads[NUM];
-  void *thread_result;
   int ids[NUM];
 
+  pthread_barrier_init (&threads_started_barrier, NULL, NUM + 1);
+
   for (int i = 0; i < NUM; i++)
     {
-      ids[i] = i + 2;
-      pthread_create (&threads[i], NULL, work, &(ids[i]));
+      ids[i] = i;
+      pthread_create (&threads[i], NULL, work, &ids[i]);
     }
 
-  sleep (10);
-  should_spin = 0;
+  /* Wait until all threads are seen running.  */
+  pthread_barrier_wait (&threads_started_barrier);
 
-  for (int i = 0; i < NUM; i++)
-    pthread_join(threads[i], &thread_result);
+  stop_here ();
 
   return 0;
 }
diff --git a/gdb/testsuite/gdb.threads/info-threads-stopped.exp b/gdb/testsuite/gdb.threads/info-threads-stopped.exp
index 37d6622697c..d554bd7ef2c 100644
--- a/gdb/testsuite/gdb.threads/info-threads-stopped.exp
+++ b/gdb/testsuite/gdb.threads/info-threads-stopped.exp
@@ -27,28 +27,29 @@ save_vars { GDBFLAGS } {
     clean_restart $binfile
 }
 
-gdb_breakpoint "something"
-gdb_run_cmd
+if ![runto_main] {
+    return -1
+}
+
+gdb_breakpoint "stop_here"
+gdb_test_multiple "continue -a&" "" {
+    -re "Continuing.\r\n$gdb_prompt " {
+	pass $gdb_test_name
+    }
+}
 
-# Two threads hit the bp.
+set expected_hits 3
 set fill "\[^\r\n\]+"
 set num_hits 0
 gdb_test_multiple "" "hit the breakpoint" -lbl {
-    -re "\r\nThread ${fill} hit Breakpoint 1${fill}" {
+    -re "\r\nThread ${fill} hit Breakpoint ${decimal}," {
 	incr num_hits
-	if {$num_hits < 2} {
+	if {$num_hits < $expected_hits} {
 	    exp_continue
 	}
     }
-    -re "\r\n$gdb_prompt " {
-	exp_continue
-    }
 }
-gdb_assert {$num_hits == 2} "two threads hit the bp"
-
-# We are in non-stop mode.
-# Send a simple command to resync the command prompt.
-gdb_test "p 42" " = 42"
+gdb_assert {$num_hits == $expected_hits} "expected threads hit the bp"
 
 # Count the number of running/stopped threads reported
 # by the "info threads" command.  We also capture thread ids
@@ -56,36 +57,37 @@ gdb_test "p 42" " = 42"
 set running_tid "invalid"
 set stopped_tid "invalid"
 
+set eol "(?=\r\n)"
+
 foreach flag {"" "-stopped"} {
     set num_running 0
     set num_stopped 0
-    gdb_test_multiple "info threads $flag" "info threads $flag" {
-	-re "Id${fill}Target Id${fill}Frame${fill}" {
+    gdb_test_multiple "info threads $flag" "info threads $flag" -lbl {
+	-re "Id${fill}Target Id${fill}Frame${fill}${eol}" {
 	    exp_continue
 	}
-	-re "^\r\n. (${decimal})${fill}Thread ${fill}.running." {
+	-re "^\r\n. (${decimal})${fill}Thread ${fill}.running.${eol}" {
 	    incr num_running
 	    set running_tid $expect_out(1,string)
 	    exp_continue
 	}
-	-re "^\r\n. (${decimal})${fill}Thread ${fill}something ${fill}${srcfile}:${decimal}" {
+	-re "^\r\n. (${decimal})${fill}Thread ${fill}stop_here ${fill}${srcfile}:${decimal}${fill}${eol}" {
 	    incr num_stopped
 	    set stopped_tid $expect_out(1,string)
 	    exp_continue
 	}
 	-re "^\r\n$gdb_prompt $" {
-	    gdb_assert {$num_stopped == 2} "$gdb_test_name: num stopped"
-	    if {$flag eq ""} {
-		gdb_assert {$num_running == 3} "$gdb_test_name: num running"
-	    } else {
-		gdb_assert {$num_running == 0} "$gdb_test_name: num running"
-	    }
+	    pass $gdb_test_name
 	}
     }
 }
 
-gdb_assert {$running_tid != "invalid"} "found a running thread"
-gdb_assert {$stopped_tid != "invalid"} "found a stopped thread"
+gdb_assert {$num_stopped == 3} "num stopped"
+if {$flag eq ""} {
+    gdb_assert {$num_running == 2} "num running"
+} else {
+    gdb_assert {$num_running == 0} "num running"
+}
 
 # Test specifying thread ids.
 gdb_test "info threads -stopped $running_tid" \
@@ -97,11 +99,11 @@ set ws "\[ \t\]+"
 gdb_test "info threads -stopped $stopped_tid" \
     [multi_line \
 	 "${ws}Id${ws}Target Id${ws}Frame${ws}" \
-	 "${ws}${stopped_tid}${ws}Thread ${fill} something ${fill}"] \
+	 "${ws}${stopped_tid}${ws}Thread ${fill} stop_here ${fill}"] \
     "info thread -stopped for a stopped thread"
 
 gdb_test "info threads -stopped $running_tid $stopped_tid" \
     [multi_line \
 	 "${ws}Id${ws}Target Id${ws}Frame${ws}" \
-	 "${ws}${stopped_tid}${ws}Thread ${fill} something ${fill}"] \
+	 "${ws}${stopped_tid}${ws}Thread ${fill} stop_here ${fill}"] \
     "info thread -stopped for a running and a stopped thread"

base-commit: e32b976a152894c00a01e4e0a48cd1f1d82d1d39
prerequisite-patch-id: 38786aad181a17816a63708dcae88f8bffed5469
prerequisite-patch-id: f64471d0b4bbbb7cb787ae826e654baf8c1a5bf3
-- 
2.49.0


[-- Attachment #3: 0002-No-threads-matched.patch --]
[-- Type: text/x-patch, Size: 2875 bytes --]

From a8e4beca721a9fb25fc3050bac2a44360f83f743 Mon Sep 17 00:00:00 2001
From: Pedro Alves <pedro@palves.net>
Date: Thu, 24 Apr 2025 19:36:12 +0100
Subject: [PATCH 2/2] No threads matched

Change-Id: I12ea3d283319c8249807e70de890b40ad3a00f7d
---
 .../gdb.threads/info-threads-stopped.exp       |  2 +-
 gdb/thread.c                                   | 18 ++++++++----------
 2 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/gdb/testsuite/gdb.threads/info-threads-stopped.exp b/gdb/testsuite/gdb.threads/info-threads-stopped.exp
index d554bd7ef2c..660ed4aa197 100644
--- a/gdb/testsuite/gdb.threads/info-threads-stopped.exp
+++ b/gdb/testsuite/gdb.threads/info-threads-stopped.exp
@@ -91,7 +91,7 @@ if {$flag eq ""} {
 
 # Test specifying thread ids.
 gdb_test "info threads -stopped $running_tid" \
-    "No stopped threads match '$running_tid'\." \
+    "No threads matched\\." \
     "info thread -stopped for a running thread"
 
 set fill "\[^\r\n\]+"
diff --git a/gdb/thread.c b/gdb/thread.c
index 7057fa1d641..7485dcce8d6 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -1267,13 +1267,15 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
       list_emitter.emplace (uiout, "threads");
     else
       {
-	int n_threads = 0;
+	int n_matching_threads = 0;
 	/* The width of the "Target Id" column.  Grown below to
 	   accommodate the largest entry.  */
 	size_t target_id_col_width = 17;
 
 	for (thread_info *tp : all_threads ())
 	  {
+	    any_thread = true;
+
 	    /* In case REQUESTED_THREADS contains $_thread.  */
 	    if (current_thread != nullptr)
 	      switch_to_thread (current_thread);
@@ -1290,22 +1292,20 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
 	      = std::max (target_id_col_width,
 			  thread_target_id_str (tp).size ());
 
-	    ++n_threads;
+	    ++n_matching_threads;
 	  }
 
-	if (n_threads == 0)
+	if (n_matching_threads == 0)
 	  {
-	    if (requested_threads == NULL || *requested_threads == '\0')
+	    if (!any_thread)
 	      uiout->message (_("No threads.\n"));
 	    else
-	      uiout->message (_("No %sthreads match '%s'.\n"),
-			      (opts.show_stopped_threads ? "stopped " : ""),
-			      requested_threads);
+	      uiout->message (_("No threads matched.\n"));
 	    return;
 	  }
 
 	table_emitter.emplace (uiout, opts.show_global_ids ? 5 : 4,
-			       n_threads, "threads");
+			       n_matching_threads, "threads");
 
 	uiout->table_header (1, ui_left, "current", "");
 	uiout->table_header (4, ui_left, "id-in-tg", "Id");
@@ -1320,8 +1320,6 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
     for (inferior *inf : all_inferiors ())
       for (thread_info *tp : inf->threads ())
 	{
-	  any_thread = true;
-
 	  if (tp == current_thread && tp->state == THREAD_EXITED)
 	    current_exited = true;
 
-- 
2.49.0


^ permalink raw reply	[flat|nested] 32+ messages in thread

* RE: [PATCH v3 2/2] gdb: add a '-stopped' option to "info threads"
  2025-04-24 19:23     ` Pedro Alves
@ 2025-05-05 16:17       ` Aktemur, Tankut Baris
  0 siblings, 0 replies; 32+ messages in thread
From: Aktemur, Tankut Baris @ 2025-05-05 16:17 UTC (permalink / raw)
  To: Pedro Alves, gdb-patches; +Cc: guinevere, eliz

On Thursday, April 24, 2025 9:23 PM, Pedro Alves wrote:
> Hi!
> 
> On 2025-04-04 14:36, Tankut Baris Aktemur wrote:
> > Add a '-stopped' option to the "info threads" command to print stopped
> > threads only and skip the running ones.  This is a convenience flag to
> > filter out the running threads in programs that have many threads.
> >
> > Suppose we have an application with 5 threads, 2 of which have hit a
> > breakpoint.  The "info threads" command in the non-stop mode gives:
> >
> >   (gdb) info threads
> >     Id   Target Id             Frame
> >   * 1    Thread 0x7ffff7d99740 (running)
> >     2    Thread 0x7ffff7d98700 something () at file.c:30
> >     3    Thread 0x7ffff7597700 (running)
> >     4    Thread 0x7ffff6d96700 something () at file.c:30
> >     5    Thread 0x7ffff6595700 (running)
> >   (gdb)
> >
> > Using the "-stopped" flag, we get
> >
> >   (gdb) info threads -stopped
> >     Id   Target Id             Frame
> >     2    Thread 0x7ffff7d98700 something () at file.c:30
> >     4    Thread 0x7ffff6d96700 something () at file.c:30
> >   (gdb)
> >
> > When combined with a thread ID, the behavior is as follows:
> >
> >   (gdb) info threads 3
> >     Id   Target Id             Frame
> >     3    Thread 0x7ffff7597700 (running)
> >   (gdb) info threads -stopped 3
> >   No stopped threads match '3'.
> >   (gdb)
> >
> > Regression-tested on X86_64 Linux.
> >
> > Reviewed-By: Eli Zaretskii <eliz@gnu.org>
> > Reviewed-By: Guinevere Larsen <guinevere@redhat.com>
> > ---
> >  gdb/NEWS                                      |   5 +
> >  gdb/doc/gdb.texinfo                           |   6 +-
> >  gdb/testsuite/gdb.base/options.exp            |  11 +-
> >  .../gdb.threads/info-threads-stopped.c        |  78 +++++++++++++
> >  .../gdb.threads/info-threads-stopped.exp      | 107 ++++++++++++++++++
> >  gdb/thread.c                                  |  17 ++-
> >  6 files changed, 220 insertions(+), 4 deletions(-)
> >  create mode 100644 gdb/testsuite/gdb.threads/info-threads-stopped.c
> >  create mode 100644 gdb/testsuite/gdb.threads/info-threads-stopped.exp
> >
> > diff --git a/gdb/NEWS b/gdb/NEWS
> > index 6a557bb4af9..d5c55c3c938 100644
> > --- a/gdb/NEWS
> > +++ b/gdb/NEWS
> > @@ -56,6 +56,11 @@ info sharedlibrary
> >    command are now for the full memory range allocated to the shared
> >    library.
> >
> > +info threads [-gid] [-stopped] [ID]...
> > +  This command now takes an optional flag, '-stopped', that causes only
> > +  the stopped threads to be printed.  The flag can be useful to get a
> > +  reduced list when there is a large number of unstopped threads.
> 
> 
> Cool!
> 
> (I would have added -running too while at it, and make "thread apply -stopped" work too.
> 
>  And then:
> 
>   "info threads -stopped -running"
> 
>  would print both stopped and running.
> 
>  Same logic as "info lanes -active -inactive" including both active and inactive in
>  our offlist discussions.)

Hi Pedro,

Thanks a lot for the thorough review.  I'll soon send the next revision.
I also added "-running" per your suggestion, but let's please complete this
series first.  I'd like to send "thread apply -stopped" separately.

Thank you.
-Baris

 

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Sean Fennelly, Jeffrey Schneiderman, Tiffany Doon Silva
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928

^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH v4 0/3]  Option to show stopped/running threads only
  2025-04-04 13:36 ` [PATCH v3 " Tankut Baris Aktemur
                     ` (3 preceding siblings ...)
  2025-04-24 17:53   ` Pedro Alves
@ 2025-05-05 16:19   ` Tankut Baris Aktemur
  2025-05-05 16:19     ` [PATCH v4 1/3] gdb: pass info_threads_opts to print_thread_info_1 Tankut Baris Aktemur
                       ` (3 more replies)
  4 siblings, 4 replies; 32+ messages in thread
From: Tankut Baris Aktemur @ 2025-05-05 16:19 UTC (permalink / raw)
  To: gdb-patches; +Cc: guinevere, eliz, pedro

Hi,

This is v4 of a series that introduces options to filter the output of
"info threads".  V3 is available at

  https://inbox.sourceware.org/gdb-patches/cover.1743772891.git.tankut.baris.aktemur@intel.com/

In this revision I address Pedro's comments he gave on V3.

Eli had previously approved the documentation changes, but I needed to
update the docs in this revision.  Hence, I removed his "Reviewed-By"
and would like to request a doc review again.

Best regards,
Baris

Tankut Baris Aktemur (3):
  gdb: pass info_threads_opts to print_thread_info_1
  gdb: update "info threads" output when no threads match the arguments
  gdb: add '-stopped' and '-running' options to "info threads"

 gdb/NEWS                                      |  12 ++
 gdb/doc/gdb.texinfo                           |  10 +-
 gdb/testsuite/gdb.base/options.exp            |  16 ++-
 gdb/testsuite/gdb.multi/tids.exp              |   4 +-
 .../gdb.threads/current-lwp-dead.exp          |   2 +-
 .../gdb.threads/info-threads-options.c        |  77 ++++++++++
 .../gdb.threads/info-threads-options.exp      | 131 ++++++++++++++++++
 .../gdb.threads/thread-bp-deleted.exp         |   2 +-
 gdb/thread.c                                  | 122 +++++++++-------
 9 files changed, 321 insertions(+), 55 deletions(-)
 create mode 100644 gdb/testsuite/gdb.threads/info-threads-options.c
 create mode 100644 gdb/testsuite/gdb.threads/info-threads-options.exp

-- 
2.34.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Sean Fennelly, Jeffrey Schneiderman, Tiffany Doon Silva
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH v4 1/3] gdb: pass info_threads_opts to print_thread_info_1
  2025-05-05 16:19   ` [PATCH v4 0/3] Option to show stopped/running " Tankut Baris Aktemur
@ 2025-05-05 16:19     ` Tankut Baris Aktemur
  2025-05-05 16:19     ` [PATCH v4 2/3] gdb: update "info threads" output when no threads match the arguments Tankut Baris Aktemur
                       ` (2 subsequent siblings)
  3 siblings, 0 replies; 32+ messages in thread
From: Tankut Baris Aktemur @ 2025-05-05 16:19 UTC (permalink / raw)
  To: gdb-patches; +Cc: guinevere, eliz, pedro

The "info threads" command tracks its options in a struct named
'info_threads_opts', which currently has only one option.  Pass the
whole options object to helper functions, instead of passing
the option value individually.  This is a refactoring to make adding
more options easier.

Reviewed-By: Guinevere Larsen <guinevere@redhat.com>
---
 gdb/thread.c | 80 +++++++++++++++++++++++++++-------------------------
 1 file changed, 41 insertions(+), 39 deletions(-)

diff --git a/gdb/thread.c b/gdb/thread.c
index b659463ef02..3375cfcee24 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -1038,6 +1038,24 @@ pc_in_thread_step_range (CORE_ADDR pc, struct thread_info *thread)
 	  && pc < thread->control.step_range_end);
 }
 
+/* The options for the "info threads" command.  */
+
+struct info_threads_opts
+{
+  /* For "-gid".  */
+  bool show_global_ids = false;
+};
+
+static const gdb::option::option_def info_threads_option_defs[] = {
+
+  gdb::option::flag_option_def<info_threads_opts> {
+    "gid",
+    [] (info_threads_opts *opts) { return &opts->show_global_ids; },
+    N_("Show global thread IDs."),
+  },
+
+};
+
 /* Helper for print_thread_info.  Returns true if THR should be
    printed.  If REQUESTED_THREADS, a list of GDB ids/ranges, is not
    NULL, only print THR if its ID is included in the list.  GLOBAL_IDS
@@ -1046,11 +1064,13 @@ pc_in_thread_step_range (CORE_ADDR pc, struct thread_info *thread)
    is a thread from the process PID.  Otherwise, threads from all
    attached PIDs are printed.  If both REQUESTED_THREADS is not NULL
    and PID is not -1, then the thread is printed if it belongs to the
-   specified process.  Otherwise, an error is raised.  */
+   specified process.  Otherwise, an error is raised.  OPTS is the
+   options of the "info threads" command.  */
 
 static bool
-should_print_thread (const char *requested_threads, int default_inf_num,
-		     int global_ids, int pid, struct thread_info *thr)
+should_print_thread (const char *requested_threads,
+		     const info_threads_opts &opts, int default_inf_num,
+		     int global_ids, int pid, thread_info *thr)
 {
   if (requested_threads != NULL && *requested_threads != '\0')
     {
@@ -1104,8 +1124,8 @@ thread_target_id_str (thread_info *tp)
 
 static void
 do_print_thread (ui_out *uiout, const char *requested_threads,
-		 int global_ids, int pid, int show_global_ids,
-		 int default_inf_num, thread_info *tp,
+		 const info_threads_opts &opts, int global_ids,
+		 int pid, int default_inf_num, thread_info *tp,
 		 thread_info *current_thread)
 {
   int core;
@@ -1114,7 +1134,7 @@ do_print_thread (ui_out *uiout, const char *requested_threads,
   if (current_thread != nullptr)
     switch_to_thread (current_thread);
 
-  if (!should_print_thread (requested_threads, default_inf_num,
+  if (!should_print_thread (requested_threads, opts, default_inf_num,
 			    global_ids, pid, tp))
     return;
 
@@ -1130,7 +1150,7 @@ do_print_thread (ui_out *uiout, const char *requested_threads,
       uiout->field_string ("id-in-tg", print_thread_id (tp));
     }
 
-  if (show_global_ids || uiout->is_mi_like_p ())
+  if (opts.show_global_ids || uiout->is_mi_like_p ())
     uiout->field_signed ("id", tp->global_num);
 
   /* Switch to the thread (and inferior / target).  */
@@ -1191,23 +1211,22 @@ do_print_thread (ui_out *uiout, const char *requested_threads,
 
 static void
 print_thread (ui_out *uiout, const char *requested_threads,
-	      int global_ids, int pid, int show_global_ids,
+	      const info_threads_opts &opts, int global_ids, int pid,
 	      int default_inf_num, thread_info *tp, thread_info *current_thread)
 
 {
   do_with_buffered_output (do_print_thread, uiout, requested_threads,
-			   global_ids, pid, show_global_ids,
-			   default_inf_num, tp, current_thread);
+			   opts, global_ids, pid, default_inf_num, tp,
+			   current_thread);
 }
 
 /* Like print_thread_info, but in addition, GLOBAL_IDS indicates
    whether REQUESTED_THREADS is a list of global or per-inferior
-   thread ids.  */
+   thread ids.  OPTS is the options of the "info threads" command.  */
 
 static void
 print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
-		     int global_ids, int pid,
-		     int show_global_ids)
+		     const info_threads_opts &opts, int global_ids, int pid)
 {
   int default_inf_num = current_inferior ()->num;
 
@@ -1246,8 +1265,8 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
 	    if (current_thread != nullptr)
 	      switch_to_thread (current_thread);
 
-	    if (!should_print_thread (requested_threads, default_inf_num,
-				      global_ids, pid, tp))
+	    if (!should_print_thread (requested_threads, opts,
+				      default_inf_num, global_ids, pid, tp))
 	      continue;
 
 	    /* Switch inferiors so we're looking at the right
@@ -1271,12 +1290,12 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
 	    return;
 	  }
 
-	table_emitter.emplace (uiout, show_global_ids ? 5 : 4,
+	table_emitter.emplace (uiout, opts.show_global_ids ? 5 : 4,
 			       n_threads, "threads");
 
 	uiout->table_header (1, ui_left, "current", "");
 	uiout->table_header (4, ui_left, "id-in-tg", "Id");
-	if (show_global_ids)
+	if (opts.show_global_ids)
 	  uiout->table_header (4, ui_left, "id", "GId");
 	uiout->table_header (target_id_col_width, ui_left,
 			     "target-id", "Target Id");
@@ -1292,8 +1311,8 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
 	  if (tp == current_thread && tp->state == THREAD_EXITED)
 	    current_exited = true;
 
-	  print_thread (uiout, requested_threads, global_ids, pid,
-			show_global_ids, default_inf_num, tp, current_thread);
+	  print_thread (uiout, requested_threads, opts, global_ids, pid,
+			default_inf_num, tp, current_thread);
 	}
 
     /* This end scope restores the current thread and the frame
@@ -1322,27 +1341,10 @@ void
 print_thread_info (struct ui_out *uiout, const char *requested_threads,
 		   int pid)
 {
-  print_thread_info_1 (uiout, requested_threads, 1, pid, 0);
+  info_threads_opts opts;
+  print_thread_info_1 (uiout, requested_threads, opts, 1, pid);
 }
 
-/* The options for the "info threads" command.  */
-
-struct info_threads_opts
-{
-  /* For "-gid".  */
-  bool show_global_ids = false;
-};
-
-static const gdb::option::option_def info_threads_option_defs[] = {
-
-  gdb::option::flag_option_def<info_threads_opts> {
-    "gid",
-    [] (info_threads_opts *opts) { return &opts->show_global_ids; },
-    N_("Show global thread IDs."),
-  },
-
-};
-
 /* Create an option_def_group for the "info threads" options, with
    IT_OPTS as context.  */
 
@@ -1367,7 +1369,7 @@ info_threads_command (const char *arg, int from_tty)
   gdb::option::process_options
     (&arg, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, grp);
 
-  print_thread_info_1 (current_uiout, arg, 0, -1, it_opts.show_global_ids);
+  print_thread_info_1 (current_uiout, arg, it_opts, 0, -1);
 }
 
 /* Completer for the "info threads" command.  */
-- 
2.34.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Sean Fennelly, Jeffrey Schneiderman, Tiffany Doon Silva
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH v4 2/3] gdb: update "info threads" output when no threads match the arguments
  2025-05-05 16:19   ` [PATCH v4 0/3] Option to show stopped/running " Tankut Baris Aktemur
  2025-05-05 16:19     ` [PATCH v4 1/3] gdb: pass info_threads_opts to print_thread_info_1 Tankut Baris Aktemur
@ 2025-05-05 16:19     ` Tankut Baris Aktemur
  2025-05-05 17:19       ` Eli Zaretskii
  2025-05-05 16:19     ` [PATCH v4 3/3] gdb: add '-stopped' and '-running' options to "info threads" Tankut Baris Aktemur
  2025-05-09 20:54     ` [PATCH v4 0/3] Option to show stopped/running threads only Pedro Alves
  3 siblings, 1 reply; 32+ messages in thread
From: Tankut Baris Aktemur @ 2025-05-05 16:19 UTC (permalink / raw)
  To: gdb-patches; +Cc: guinevere, eliz, pedro

If "info threads" is provided with the thread ID argument but no such
threads matching the thread ID(s) are found, GDB prints

  No threads match '<ID...>'.

Update this output to the more generalized

  No threads matched.

The intention is that the next patch, and potentially future ones,
will extend the command with more filter/match arguments.  We cannot
customize the output to each such argument.  Hence, be more generic.
---
 gdb/NEWS                                        | 7 +++++++
 gdb/testsuite/gdb.multi/tids.exp                | 4 ++--
 gdb/testsuite/gdb.threads/current-lwp-dead.exp  | 2 +-
 gdb/testsuite/gdb.threads/thread-bp-deleted.exp | 2 +-
 gdb/thread.c                                    | 3 +--
 5 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index a82b7e3342c..18a8b7475b4 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -90,6 +90,13 @@ info sharedlibrary
   command are now for the full memory range allocated to the shared
   library.
 
+info threads [-gid] [ID]...
+  If no threads match the given ID(s), GDB now prints
+
+    No threads matched.
+
+  without printing the provided argument.
+
 * GDB-internal Thread Local Storage (TLS) support
 
   ** Linux targets for the x86_64, aarch64, ppc64, s390x, and riscv
diff --git a/gdb/testsuite/gdb.multi/tids.exp b/gdb/testsuite/gdb.multi/tids.exp
index b84f9080cbd..dab6275dc03 100644
--- a/gdb/testsuite/gdb.multi/tids.exp
+++ b/gdb/testsuite/gdb.multi/tids.exp
@@ -290,7 +290,7 @@ with_test_prefix "two inferiors" {
     # Try both the convenience variable and the literal number.
     foreach thr {"\$thr" "20" "1.20" "\$inf.1" "30.1" } {
 	set expected [string_to_regexp $thr]
-	gdb_test "info threads $thr" "No threads match '${expected}'."
+	gdb_test "info threads $thr" "No threads matched\\."
 	# "info threads" works like a filter.  If there's any other
 	# valid thread in the list, there's no error.
 	info_threads "$thr 1.1" "1.1"
@@ -412,7 +412,7 @@ with_test_prefix "two inferiors" {
 
     # Check that we do parse the inferior number and don't confuse it.
     gdb_test "info threads 3.1" \
-	"No threads match '3.1'\."
+	"No threads matched\\."
 }
 
 if { [allow_python_tests] } {
diff --git a/gdb/testsuite/gdb.threads/current-lwp-dead.exp b/gdb/testsuite/gdb.threads/current-lwp-dead.exp
index 7aa7ab951b5..c8364df0b84 100644
--- a/gdb/testsuite/gdb.threads/current-lwp-dead.exp
+++ b/gdb/testsuite/gdb.threads/current-lwp-dead.exp
@@ -47,6 +47,6 @@ gdb_breakpoint $line
 gdb_continue_to_breakpoint "fn_return" ".*at-fn_return.*"
 
 # Confirm thread 2 is really gone.
-gdb_test "info threads 2" "No threads match '2'\\."
+gdb_test "info threads 2" "No threads matched\\."
 
 gdb_continue_to_end "" continue 1
diff --git a/gdb/testsuite/gdb.threads/thread-bp-deleted.exp b/gdb/testsuite/gdb.threads/thread-bp-deleted.exp
index 2eadd380370..8cabb709c0c 100644
--- a/gdb/testsuite/gdb.threads/thread-bp-deleted.exp
+++ b/gdb/testsuite/gdb.threads/thread-bp-deleted.exp
@@ -147,7 +147,7 @@ if {$is_remote} {
 	    exp_continue
 	}
 
-	-re "No threads match '99'\\.\r\n$gdb_prompt $" {
+	-re "No threads matched\\.\r\n$gdb_prompt $" {
 	    if {!$saw_thread_exited && !$saw_bp_deleted && $attempt_count > 0} {
 		sleep 1
 		incr attempt_count -1
diff --git a/gdb/thread.c b/gdb/thread.c
index 3375cfcee24..d84d326a8c3 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -1285,8 +1285,7 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
 	    if (requested_threads == NULL || *requested_threads == '\0')
 	      uiout->message (_("No threads.\n"));
 	    else
-	      uiout->message (_("No threads match '%s'.\n"),
-			      requested_threads);
+	      uiout->message (_("No threads matched.\n"));
 	    return;
 	  }
 
-- 
2.34.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Sean Fennelly, Jeffrey Schneiderman, Tiffany Doon Silva
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH v4 3/3] gdb: add '-stopped' and '-running' options to "info threads"
  2025-05-05 16:19   ` [PATCH v4 0/3] Option to show stopped/running " Tankut Baris Aktemur
  2025-05-05 16:19     ` [PATCH v4 1/3] gdb: pass info_threads_opts to print_thread_info_1 Tankut Baris Aktemur
  2025-05-05 16:19     ` [PATCH v4 2/3] gdb: update "info threads" output when no threads match the arguments Tankut Baris Aktemur
@ 2025-05-05 16:19     ` Tankut Baris Aktemur
  2025-05-05 17:21       ` Eli Zaretskii
  2025-05-09 20:54     ` [PATCH v4 0/3] Option to show stopped/running threads only Pedro Alves
  3 siblings, 1 reply; 32+ messages in thread
From: Tankut Baris Aktemur @ 2025-05-05 16:19 UTC (permalink / raw)
  To: gdb-patches; +Cc: guinevere, eliz, pedro

Add two options to "info threads": `-stopped` and `-running`.

The purpose of these options is to filter the output of the command.
The `-stopped` option means "print stopped threads only" and,
similarly, `-running` means "print the running threads only".  When
both options are provided by the user, the indication is that the user
wants the union.  That is, the output contains both stopped and
running threads.

Suppose we have an application with 5 threads, 2 of which have hit a
breakpoint.  The "info threads" command in the non-stop mode gives:

  (gdb) info threads
    Id   Target Id             Frame
  * 1    Thread 0x7ffff7d99740 (running)
    2    Thread 0x7ffff7d98700 something () at file.c:30
    3    Thread 0x7ffff7597700 (running)
    4    Thread 0x7ffff6d96700 something () at file.c:30
    5    Thread 0x7ffff6595700 (running)
  (gdb)

Using the "-stopped" flag, we get

  (gdb) info threads -stopped
    Id   Target Id             Frame
    2    Thread 0x7ffff7d98700 something () at file.c:30
    4    Thread 0x7ffff6d96700 something () at file.c:30
  (gdb)

Using the "-running" flag, we get

  (gdb) info threads -running
    Id   Target Id             Frame
  * 1    Thread 0x7ffff7d99740 (running)
    3    Thread 0x7ffff7597700 (running)
    5    Thread 0x7ffff6595700 (running)
  (gdb)

Using both flags prints all:

  (gdb) info threads -stopped -running
    Id   Target Id             Frame
  * 1    Thread 0x7ffff7d99740 (running)
    2    Thread 0x7ffff7d98700 something () at file.c:30
    3    Thread 0x7ffff7597700 (running)
    4    Thread 0x7ffff6d96700 something () at file.c:30
    5    Thread 0x7ffff6595700 (running)
  (gdb)

When combined with a thread ID, filtering applies to those threads that
are matched by the ID.

  (gdb) info threads 3
    Id   Target Id             Frame
    3    Thread 0x7ffff7597700 (running)
  (gdb) info threads -stopped 3
  No threads matched.
  (gdb)

Regression-tested on X86_64 Linux.

Reviewed-By: Guinevere Larsen <guinevere@redhat.com>
---
 gdb/NEWS                                      |  11 +-
 gdb/doc/gdb.texinfo                           |  10 +-
 gdb/testsuite/gdb.base/options.exp            |  16 ++-
 .../gdb.threads/info-threads-options.c        |  77 ++++++++++
 .../gdb.threads/info-threads-options.exp      | 131 ++++++++++++++++++
 gdb/thread.c                                  |  41 ++++--
 6 files changed, 272 insertions(+), 14 deletions(-)
 create mode 100644 gdb/testsuite/gdb.threads/info-threads-options.c
 create mode 100644 gdb/testsuite/gdb.threads/info-threads-options.exp

diff --git a/gdb/NEWS b/gdb/NEWS
index 18a8b7475b4..70729b501cc 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -90,12 +90,17 @@ info sharedlibrary
   command are now for the full memory range allocated to the shared
   library.
 
-info threads [-gid] [ID]...
-  If no threads match the given ID(s), GDB now prints
+info threads [-gid] [-stopped] [-running] [ID]...
+  If no threads match the given ID(s) or filter options, GDB now prints
 
     No threads matched.
 
-  without printing the provided argument.
+  without printing the provided arguments.  The newly added '-stopped'
+  option makes GDB list the stopped threads only.  Similarly,
+  '-running' makes GDB list the running threads only.  If both options
+  are given together, GDB lists the union; that is, both stopped and
+  running threads are listed.  These new flags can be useful to get a
+  reduced list when there is a large number of threads.
 
 * GDB-internal Thread Local Storage (TLS) support
 
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index b9fc160a171..989cc36fbee 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -3807,7 +3807,7 @@ Thread 1 "main" received signal SIGINT, Interrupt.
 @table @code
 @anchor{info_threads}
 @kindex info threads
-@item info threads @r{[}-gid@r{]} @r{[}@var{thread-id-list}@r{]}
+@item info threads @r{[}-gid@r{]} @r{[}-stopped@r{]} @r{[}-running@r{]} @r{[}@var{thread-id-list}@r{]}
 
 Display information about one or more threads.  With no arguments
 displays information about all threads.  You can specify the list of
@@ -3857,6 +3857,14 @@ If you're debugging multiple inferiors, @value{GDBN} displays thread
 IDs using the qualified @var{inferior-num}.@var{thread-num} format.
 Otherwise, only @var{thread-num} is shown.
 
+If you specify the @samp{-stopped} option, @value{GDBN} filters the
+output of the command to print the stopped threads only.  Similarly,
+if you specify the @samp{-running} option, @value{GDBN} filters the
+output to print the running threads only.  These options can be
+helpful to reduce the output list if there is a large number of
+threads.  If you specify both options, @value{GDBN} prints the union;
+both stopped and running threads are printed.
+
 If you specify the @samp{-gid} option, @value{GDBN} displays a column
 indicating each thread's global thread ID:
 
diff --git a/gdb/testsuite/gdb.base/options.exp b/gdb/testsuite/gdb.base/options.exp
index 7822e4a0baa..a0947e2f6f4 100644
--- a/gdb/testsuite/gdb.base/options.exp
+++ b/gdb/testsuite/gdb.base/options.exp
@@ -508,12 +508,26 @@ proc_with_prefix test-thread-apply {} {
 proc_with_prefix test-info-threads {} {
     test_gdb_complete_multiple "info threads " "" "" {
 	"-gid"
+	"-running"
+	"-stopped"
 	"ID"
     }
 
+    test_gdb_complete_multiple "info threads " "-" "" {
+	"-gid"
+	"-running"
+	"-stopped"
+    }
+
     test_gdb_complete_unique \
-	"info threads -" \
+	"info threads -g" \
 	"info threads -gid"
+    test_gdb_complete_unique \
+	"info threads -r" \
+	"info threads -running"
+    test_gdb_complete_unique \
+	"info threads -s" \
+	"info threads -stopped"
 
     # "ID" isn't really something the user can type.
     test_gdb_complete_none "info threads I"
diff --git a/gdb/testsuite/gdb.threads/info-threads-options.c b/gdb/testsuite/gdb.threads/info-threads-options.c
new file mode 100644
index 00000000000..2c4cd854bb7
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/info-threads-options.c
@@ -0,0 +1,77 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2022-2025 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#define NUM 4
+
+static pthread_barrier_t threads_started_barrier;
+
+static void
+stop_here ()
+{
+}
+
+static void
+spin ()
+{
+  while (1)
+    usleep (1);
+}
+
+static void *
+work (void *arg)
+{
+  int id = *(int *) arg;
+
+  pthread_barrier_wait (&threads_started_barrier);
+
+  if (id % 2 == 0)
+    stop_here ();
+  else
+    spin ();
+
+  pthread_exit (NULL);
+}
+
+int
+main ()
+{
+  /* Ensure we stop if GDB crashes and DejaGNU fails to kill us.  */
+  alarm (10);
+
+  pthread_t threads[NUM];
+  int ids[NUM];
+
+  pthread_barrier_init (&threads_started_barrier, NULL, NUM + 1);
+
+  for (int i = 0; i < NUM; i++)
+    {
+      ids[i] = i;
+      pthread_create (&threads[i], NULL, work, &ids[i]);
+    }
+
+  /* Wait until all threads are seen running.  */
+  pthread_barrier_wait (&threads_started_barrier);
+
+  stop_here ();
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.threads/info-threads-options.exp b/gdb/testsuite/gdb.threads/info-threads-options.exp
new file mode 100644
index 00000000000..38e4e67f08b
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/info-threads-options.exp
@@ -0,0 +1,131 @@
+# Copyright (C) 2022-2025 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test the filter flags of the "info threads" command.
+
+standard_testfile
+
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
+	 executable debug] != "" } {
+    return -1
+}
+
+save_vars { GDBFLAGS } {
+    append GDBFLAGS " -ex \"set non-stop on\""
+    clean_restart $binfile
+}
+
+if ![runto_main] {
+    return -1
+}
+
+gdb_breakpoint "stop_here"
+gdb_test_multiple "continue -a&" "" {
+    -re "Continuing.\r\n$gdb_prompt " {
+	pass $gdb_test_name
+    }
+}
+
+set expected_hits 3
+set fill "\[^\r\n\]+"
+set num_hits 0
+gdb_test_multiple "" "hit the breakpoint" -lbl {
+    -re "\r\nThread ${fill} hit Breakpoint ${decimal}," {
+	incr num_hits
+	if {$num_hits < $expected_hits} {
+	    exp_continue
+	}
+    }
+}
+gdb_assert {$num_hits == $expected_hits} "expected threads hit the bp"
+
+# Count the number of running/stopped threads reported
+# by the "info threads" command.  We also capture thread ids
+# for additional tests.
+set running_tid "invalid"
+set stopped_tid "invalid"
+
+set eol "(?=\r\n)"
+
+foreach_with_prefix flag {"" "-running" "-stopped" "-running -stopped"} {
+    set num_running 0
+    set num_stopped 0
+    gdb_test_multiple "info threads $flag" "info threads $flag" -lbl {
+	-re "Id${fill}Target Id${fill}Frame${fill}${eol}" {
+	    exp_continue
+	}
+	-re "^\r\n. (${decimal})${fill}Thread ${fill}.running.${eol}" {
+	    incr num_running
+	    set running_tid $expect_out(1,string)
+	    exp_continue
+	}
+	-re "^\r\n. (${decimal})${fill}Thread ${fill}stop_here ${fill}${eol}" {
+	    incr num_stopped
+	    set stopped_tid $expect_out(1,string)
+	    exp_continue
+	}
+	-re "^\r\n$gdb_prompt $" {
+	    pass $gdb_test_name
+	}
+    }
+
+    if {$flag eq "-running"} {
+	gdb_assert {$num_running == 2} "num running"
+	gdb_assert {$num_stopped == 0} "num stopped"
+    } elseif {$flag  eq "-stopped"} {
+	gdb_assert {$num_running == 0} "num running"
+	gdb_assert {$num_stopped == 3} "num stopped"
+    } else {
+	gdb_assert {$num_running == 2} "num running"
+	gdb_assert {$num_stopped == 3} "num stopped"
+    }
+}
+
+verbose -log "running_tid=$running_tid, stopped_tid=$stopped_tid"
+
+# Test specifying thread ids.
+gdb_test "info threads -running $stopped_tid" \
+    "No threads matched\\." \
+    "info thread -running for a stopped thread"
+gdb_test "info threads -stopped $running_tid" \
+    "No threads matched\\." \
+    "info thread -stopped for a running thread"
+
+set ws "\[ \t\]+"
+foreach tid "\"$running_tid\" \"$running_tid $stopped_tid\"" {
+    gdb_test "info threads -running $tid" \
+	[multi_line \
+	     "${ws}Id${ws}Target Id${ws}Frame${ws}" \
+	     "${ws}${running_tid}${ws}Thread ${fill}.running."] \
+	"info thread -running with [llength $tid] thread ids"
+}
+
+foreach tid "\"$stopped_tid\" \"$stopped_tid $running_tid\"" {
+    gdb_test "info threads -stopped $tid" \
+	[multi_line \
+	     "${ws}Id${ws}Target Id${ws}Frame${ws}" \
+	     "${ws}${stopped_tid}${ws}Thread ${fill} stop_here ${fill}"] \
+	"info thread -stopped with [llength $tid] thread ids"
+}
+
+gdb_test_multiple "info threads -stopped -running $stopped_tid $running_tid" \
+    "filter flags and tids combined" {
+    -re -wrap ".*stop_here.*running.*" {
+	pass $gdb_test_name
+    }
+    -re -wrap ".*running.*stop_here.*" {
+	pass $gdb_test_name
+    }
+}
diff --git a/gdb/thread.c b/gdb/thread.c
index d84d326a8c3..0228027fb92 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -1044,6 +1044,10 @@ struct info_threads_opts
 {
   /* For "-gid".  */
   bool show_global_ids = false;
+  /* For "-running".  */
+  bool show_running_threads = false;
+  /* For "-stopped".  */
+  bool show_stopped_threads = false;
 };
 
 static const gdb::option::option_def info_threads_option_defs[] = {
@@ -1053,7 +1057,16 @@ static const gdb::option::option_def info_threads_option_defs[] = {
     [] (info_threads_opts *opts) { return &opts->show_global_ids; },
     N_("Show global thread IDs."),
   },
-
+  gdb::option::flag_option_def<info_threads_opts> {
+    "running",
+    [] (info_threads_opts *opts) { return &opts->show_running_threads; },
+    N_("Show running threads only."),
+  },
+  gdb::option::flag_option_def<info_threads_opts> {
+    "stopped",
+    [] (info_threads_opts *opts) { return &opts->show_stopped_threads; },
+    N_("Show stopped threads only."),
+  },
 };
 
 /* Helper for print_thread_info.  Returns true if THR should be
@@ -1095,7 +1108,17 @@ should_print_thread (const char *requested_threads,
   if (thr->state == THREAD_EXITED)
     return false;
 
-  return true;
+  bool is_stopped = (thr->state == THREAD_STOPPED);
+  if (opts.show_stopped_threads && is_stopped)
+    return true;
+
+  bool is_running = (thr->state == THREAD_RUNNING);
+  if (opts.show_running_threads && is_running)
+    return true;
+
+  /* If the user did not pass a filter flag, show the thread.  */
+  return (!opts.show_stopped_threads
+	  && !opts.show_running_threads);
 }
 
 /* Return the string to display in "info threads"'s "Target Id"
@@ -1254,13 +1277,15 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
       list_emitter.emplace (uiout, "threads");
     else
       {
-	int n_threads = 0;
+	int n_matching_threads = 0;
 	/* The width of the "Target Id" column.  Grown below to
 	   accommodate the largest entry.  */
 	size_t target_id_col_width = 17;
 
 	for (thread_info *tp : all_threads ())
 	  {
+	    any_thread = true;
+
 	    /* In case REQUESTED_THREADS contains $_thread.  */
 	    if (current_thread != nullptr)
 	      switch_to_thread (current_thread);
@@ -1277,12 +1302,12 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
 	      = std::max (target_id_col_width,
 			  thread_target_id_str (tp).size ());
 
-	    ++n_threads;
+	    ++n_matching_threads;
 	  }
 
-	if (n_threads == 0)
+	if (n_matching_threads == 0)
 	  {
-	    if (requested_threads == NULL || *requested_threads == '\0')
+	    if (!any_thread)
 	      uiout->message (_("No threads.\n"));
 	    else
 	      uiout->message (_("No threads matched.\n"));
@@ -1290,7 +1315,7 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
 	  }
 
 	table_emitter.emplace (uiout, opts.show_global_ids ? 5 : 4,
-			       n_threads, "threads");
+			       n_matching_threads, "threads");
 
 	uiout->table_header (1, ui_left, "current", "");
 	uiout->table_header (4, ui_left, "id-in-tg", "Id");
@@ -1305,8 +1330,6 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
     for (inferior *inf : all_inferiors ())
       for (thread_info *tp : inf->threads ())
 	{
-	  any_thread = true;
-
 	  if (tp == current_thread && tp->state == THREAD_EXITED)
 	    current_exited = true;
 
-- 
2.34.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Sean Fennelly, Jeffrey Schneiderman, Tiffany Doon Silva
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v4 2/3] gdb: update "info threads" output when no threads match the arguments
  2025-05-05 16:19     ` [PATCH v4 2/3] gdb: update "info threads" output when no threads match the arguments Tankut Baris Aktemur
@ 2025-05-05 17:19       ` Eli Zaretskii
  0 siblings, 0 replies; 32+ messages in thread
From: Eli Zaretskii @ 2025-05-05 17:19 UTC (permalink / raw)
  To: Tankut Baris Aktemur; +Cc: gdb-patches, guinevere, pedro

> From: Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
> Cc: guinevere@redhat.com,
> 	eliz@gnu.org,
> 	pedro@palves.net
> Date: Mon,  5 May 2025 18:19:30 +0200
> 
> If "info threads" is provided with the thread ID argument but no such
> threads matching the thread ID(s) are found, GDB prints
> 
>   No threads match '<ID...>'.
> 
> Update this output to the more generalized
> 
>   No threads matched.
> 
> The intention is that the next patch, and potentially future ones,
> will extend the command with more filter/match arguments.  We cannot
> customize the output to each such argument.  Hence, be more generic.
> ---
>  gdb/NEWS                                        | 7 +++++++
>  gdb/testsuite/gdb.multi/tids.exp                | 4 ++--
>  gdb/testsuite/gdb.threads/current-lwp-dead.exp  | 2 +-
>  gdb/testsuite/gdb.threads/thread-bp-deleted.exp | 2 +-
>  gdb/thread.c                                    | 3 +--
>  5 files changed, 12 insertions(+), 6 deletions(-)

Thanks, the NEWS part is okay,

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v4 3/3] gdb: add '-stopped' and '-running' options to "info threads"
  2025-05-05 16:19     ` [PATCH v4 3/3] gdb: add '-stopped' and '-running' options to "info threads" Tankut Baris Aktemur
@ 2025-05-05 17:21       ` Eli Zaretskii
  0 siblings, 0 replies; 32+ messages in thread
From: Eli Zaretskii @ 2025-05-05 17:21 UTC (permalink / raw)
  To: Tankut Baris Aktemur; +Cc: gdb-patches, guinevere, pedro

> From: Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
> Cc: guinevere@redhat.com,
> 	eliz@gnu.org,
> 	pedro@palves.net
> Date: Mon,  5 May 2025 18:19:31 +0200
> 
> Add two options to "info threads": `-stopped` and `-running`.
> 
> The purpose of these options is to filter the output of the command.
> The `-stopped` option means "print stopped threads only" and,
> similarly, `-running` means "print the running threads only".  When
> both options are provided by the user, the indication is that the user
> wants the union.  That is, the output contains both stopped and
> running threads.
> 
> Suppose we have an application with 5 threads, 2 of which have hit a
> breakpoint.  The "info threads" command in the non-stop mode gives:
> 
>   (gdb) info threads
>     Id   Target Id             Frame
>   * 1    Thread 0x7ffff7d99740 (running)
>     2    Thread 0x7ffff7d98700 something () at file.c:30
>     3    Thread 0x7ffff7597700 (running)
>     4    Thread 0x7ffff6d96700 something () at file.c:30
>     5    Thread 0x7ffff6595700 (running)
>   (gdb)
> 
> Using the "-stopped" flag, we get
> 
>   (gdb) info threads -stopped
>     Id   Target Id             Frame
>     2    Thread 0x7ffff7d98700 something () at file.c:30
>     4    Thread 0x7ffff6d96700 something () at file.c:30
>   (gdb)
> 
> Using the "-running" flag, we get
> 
>   (gdb) info threads -running
>     Id   Target Id             Frame
>   * 1    Thread 0x7ffff7d99740 (running)
>     3    Thread 0x7ffff7597700 (running)
>     5    Thread 0x7ffff6595700 (running)
>   (gdb)
> 
> Using both flags prints all:
> 
>   (gdb) info threads -stopped -running
>     Id   Target Id             Frame
>   * 1    Thread 0x7ffff7d99740 (running)
>     2    Thread 0x7ffff7d98700 something () at file.c:30
>     3    Thread 0x7ffff7597700 (running)
>     4    Thread 0x7ffff6d96700 something () at file.c:30
>     5    Thread 0x7ffff6595700 (running)
>   (gdb)
> 
> When combined with a thread ID, filtering applies to those threads that
> are matched by the ID.
> 
>   (gdb) info threads 3
>     Id   Target Id             Frame
>     3    Thread 0x7ffff7597700 (running)
>   (gdb) info threads -stopped 3
>   No threads matched.
>   (gdb)
> 
> Regression-tested on X86_64 Linux.
> 
> Reviewed-By: Guinevere Larsen <guinevere@redhat.com>
> ---
>  gdb/NEWS                                      |  11 +-
>  gdb/doc/gdb.texinfo                           |  10 +-
>  gdb/testsuite/gdb.base/options.exp            |  16 ++-
>  .../gdb.threads/info-threads-options.c        |  77 ++++++++++
>  .../gdb.threads/info-threads-options.exp      | 131 ++++++++++++++++++
>  gdb/thread.c                                  |  41 ++++--
>  6 files changed, 272 insertions(+), 14 deletions(-)
>  create mode 100644 gdb/testsuite/gdb.threads/info-threads-options.c
>  create mode 100644 gdb/testsuite/gdb.threads/info-threads-options.exp

Thanks.

The documentation parts are okay, but my suggestion is to drop the
part that talks about "union": it adds nothing useful to the
description.  IOW, this:

  If you specify both options, @value{GDBN} prints both stopped and
  running threads.

is enough and tells the whole story.

Reviewed-By: Eli Zaretskii <eliz@gnu.org>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v4 0/3] Option to show stopped/running threads only
  2025-05-05 16:19   ` [PATCH v4 0/3] Option to show stopped/running " Tankut Baris Aktemur
                       ` (2 preceding siblings ...)
  2025-05-05 16:19     ` [PATCH v4 3/3] gdb: add '-stopped' and '-running' options to "info threads" Tankut Baris Aktemur
@ 2025-05-09 20:54     ` Pedro Alves
  3 siblings, 0 replies; 32+ messages in thread
From: Pedro Alves @ 2025-05-09 20:54 UTC (permalink / raw)
  To: Tankut Baris Aktemur, gdb-patches; +Cc: guinevere, eliz

On 2025-05-05 17:19, Tankut Baris Aktemur wrote:
> Hi,
> 
> This is v4 of a series that introduces options to filter the output of
> "info threads".  V3 is available at
> 
>   https://inbox.sourceware.org/gdb-patches/cover.1743772891.git.tankut.baris.aktemur@intel.com/
> 
> In this revision I address Pedro's comments he gave on V3.
> 
> Eli had previously approved the documentation changes, but I needed to
> update the docs in this revision.  Hence, I removed his "Reviewed-By"
> and would like to request a doc review again.

Thank you!

For the series:
  Approved-by: Pedro Alves <pedro@palves.net>

Pedro Alves

> 
> Best regards,
> Baris
> 
> Tankut Baris Aktemur (3):
>   gdb: pass info_threads_opts to print_thread_info_1
>   gdb: update "info threads" output when no threads match the arguments
>   gdb: add '-stopped' and '-running' options to "info threads"
> 
>  gdb/NEWS                                      |  12 ++
>  gdb/doc/gdb.texinfo                           |  10 +-
>  gdb/testsuite/gdb.base/options.exp            |  16 ++-
>  gdb/testsuite/gdb.multi/tids.exp              |   4 +-
>  .../gdb.threads/current-lwp-dead.exp          |   2 +-
>  .../gdb.threads/info-threads-options.c        |  77 ++++++++++
>  .../gdb.threads/info-threads-options.exp      | 131 ++++++++++++++++++
>  .../gdb.threads/thread-bp-deleted.exp         |   2 +-
>  gdb/thread.c                                  | 122 +++++++++-------
>  9 files changed, 321 insertions(+), 55 deletions(-)
>  create mode 100644 gdb/testsuite/gdb.threads/info-threads-options.c
>  create mode 100644 gdb/testsuite/gdb.threads/info-threads-options.exp
> 


^ permalink raw reply	[flat|nested] 32+ messages in thread

end of thread, other threads:[~2025-05-09 20:55 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-04-05  9:19 [PATCH 0/3] Option to show stopped threads only Tankut Baris Aktemur via Gdb-patches
2023-04-05  9:20 ` [PATCH 1/3] gdb: pass info_threads_opts to print_thread_info_1 Tankut Baris Aktemur via Gdb-patches
2023-04-05  9:20 ` [PATCH 2/3] gdb, doc: add the missing '-gid' option to 'info threads' Tankut Baris Aktemur via Gdb-patches
2023-04-05  9:56   ` Eli Zaretskii via Gdb-patches
2023-04-05 10:12     ` Aktemur, Tankut Baris via Gdb-patches
2023-04-05  9:20 ` [PATCH 3/3] gdb: add a '-stopped' option to "info threads" Tankut Baris Aktemur via Gdb-patches
2023-04-05 10:00   ` Eli Zaretskii via Gdb-patches
2023-04-05 10:19     ` Aktemur, Tankut Baris via Gdb-patches
2023-04-05 10:50       ` Eli Zaretskii via Gdb-patches
2023-04-05 11:31         ` Aktemur, Tankut Baris via Gdb-patches
2023-04-05 11:56           ` Eli Zaretskii via Gdb-patches
2025-04-24 14:50           ` Pedro Alves
2025-03-18 18:04 ` [PATCH v2 0/2] Option to show stopped threads only Tankut Baris Aktemur
2025-03-18 18:05   ` [PATCH v2 1/2] gdb: pass info_threads_opts to print_thread_info_1 Tankut Baris Aktemur
2025-03-18 18:05   ` [PATCH v2 2/2] gdb: add a '-stopped' option to "info threads" Tankut Baris Aktemur
2025-03-28 16:38   ` [PATCH v2 0/2] Option to show stopped threads only Guinevere Larsen
2025-04-04 13:39     ` Aktemur, Tankut Baris
2025-04-04 13:36 ` [PATCH v3 " Tankut Baris Aktemur
2025-04-04 13:36   ` [PATCH v3 1/2] gdb: pass info_threads_opts to print_thread_info_1 Tankut Baris Aktemur
2025-04-24 18:09     ` Pedro Alves
2025-04-04 13:36   ` [PATCH v3 2/2] gdb: add a '-stopped' option to "info threads" Tankut Baris Aktemur
2025-04-24 19:23     ` Pedro Alves
2025-05-05 16:17       ` Aktemur, Tankut Baris
2025-04-23  8:00   ` [PATCH v3 0/2] Option to show stopped threads only Aktemur, Tankut Baris
2025-04-24 17:53   ` Pedro Alves
2025-05-05 16:19   ` [PATCH v4 0/3] Option to show stopped/running " Tankut Baris Aktemur
2025-05-05 16:19     ` [PATCH v4 1/3] gdb: pass info_threads_opts to print_thread_info_1 Tankut Baris Aktemur
2025-05-05 16:19     ` [PATCH v4 2/3] gdb: update "info threads" output when no threads match the arguments Tankut Baris Aktemur
2025-05-05 17:19       ` Eli Zaretskii
2025-05-05 16:19     ` [PATCH v4 3/3] gdb: add '-stopped' and '-running' options to "info threads" Tankut Baris Aktemur
2025-05-05 17:21       ` Eli Zaretskii
2025-05-09 20:54     ` [PATCH v4 0/3] Option to show stopped/running threads only Pedro Alves

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox