Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH] gdb/Windows: Make windows-nat skip iterating GPU threads
@ 2026-06-19 16:38 Pedro Alves
  0 siblings, 0 replies; only message in thread
From: Pedro Alves @ 2026-06-19 16:38 UTC (permalink / raw)
  To: gdb-patches

When the AMD GPU dbgapi target is pushed on the stack, the GPU threads
are put in the same inferior thread list as the CPU threads.

all_windows_threads() returns an iterator that walks all threads that
have an inferior whose process_target() returns the Windows target.
So it ends up walking GPU threads as well, which is incorrect and
leads to crashes inside gdb/windows-nat.c.  E.g.:

 (gdb) interrupt -a
 Thread 1 received signal SIGSEGV, Segmentation fault.
 0x00007ff6bf27ad9b in windows_nat_target::stop_one_thread (this=0x11b7850, th=0x0, stopping_kind=windows_nat::SK_EXTERNAL) at .../gdb/windows-nat.c:1984
 ...

 (gdb) detach
 Thread 1 received signal SIGSEGV, Segmentation fault.
 0x00007ff774ead9ee in windows_nat_target::detach (this=0x12a77c0, inf=0x1299460, from_tty=0) at .../gdb/windows-nat.c:3047
 ...

Fix this by:

 - Making as_windows_thread_info use dynamic_cast instead of
   gdb::checked_static_cast, so only CPU threads return non-NULL.

 - Making the windows threads iterator operator++ skip threads for
   which as_windows_thread_info() returns NULL.  Same for
   all_windows_threads_range::begin().

 - Adjusting a few spots that iterate over all threads instead of
   using all_windows_threads (because they need info from the
   thread_info object) to likewise skip non-Windows threads.

No new test, as the existing gdb.rocm/ tests would catch this.  We
just can't run them yet due to a few more missing Windows pieces.

Change-Id: If98caf405a7373d95d885dfd31ac491fe4b01c60
---
 gdb/windows-nat.c | 38 ++++++++++++++++++++++++++++++++++----
 gdb/windows-nat.h | 19 ++++++++++++-------
 2 files changed, 46 insertions(+), 11 deletions(-)

diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index 3399b8c3303..7cdee85c9f0 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -320,6 +320,31 @@ static const struct xlate_exception xlate[] =
 
 #endif /* 0 */
 
+void
+all_windows_threads_iterator::advance ()
+{
+  /* Skip threads owned by targets on the target stack other than
+     windows-nat.  E.g., GPU threads.  */
+  do
+    {
+      ++m_base_iter;
+    }
+  while (m_base_iter != all_non_exited_threads_iterator {}
+	 && as_windows_thread_info (&*m_base_iter) == nullptr);
+}
+
+all_windows_threads_iterator
+all_windows_threads_range::begin () const
+{
+  /* Find the first thread owned by the windows-nat target, if
+     any.  */
+  auto begin = m_base_range.begin ();
+  while (begin != m_base_range.end ()
+	 && as_windows_thread_info (&*begin) == nullptr)
+    ++begin;
+  return all_windows_threads_iterator (begin);
+}
+
 void
 check (BOOL ok, const char *file, int line)
 {
@@ -1332,10 +1357,11 @@ windows_nat_target::stop_interrupt (ptid_t ptid, bool stop_on_first_match)
 {
   for (thread_info &thr : all_non_exited_threads (this))
     {
-      if (!thr.ptid.matches (ptid))
+      auto *w_th = as_windows_thread_info (&thr);
+      if (w_th == nullptr || !thr.ptid.matches (ptid))
 	continue;
 
-      if (stop_one_thread (as_windows_thread_info (&thr), SK_EXTERNAL))
+      if (stop_one_thread (w_th, SK_EXTERNAL))
 	{
 	  if (stop_on_first_match)
 	    return;
@@ -1420,7 +1446,8 @@ windows_nat_target::get_windows_debug_event
 	continue;
 
       auto *th = as_windows_thread_info (&thread);
-      if (thread.internal_state () == THREAD_INT_RUNNING
+      if (th != nullptr
+	  && thread.internal_state () == THREAD_INT_RUNNING
 	  && th->suspended
 	  && th->pending_status.kind () != TARGET_WAITKIND_IGNORE)
 	{
@@ -2308,9 +2335,12 @@ windows_nat_target::detach (inferior *inf, int from_tty)
      flag.  */
   for (thread_info &thr : inf->non_exited_threads ())
     {
+      auto *w_th = as_windows_thread_info (&thr);
+      if (w_th == nullptr)
+	continue;
+
       if (thr.internal_state () != THREAD_INT_RUNNING)
 	{
-	  windows_thread_info *w_th = windows_process->find_thread (thr.ptid);
 	  gdb_signal signo = get_detach_signal (this, thr.ptid);
 
 	  if (signo != w_th->last_sig
diff --git a/gdb/windows-nat.h b/gdb/windows-nat.h
index cbe5429fd84..8972e56feea 100644
--- a/gdb/windows-nat.h
+++ b/gdb/windows-nat.h
@@ -106,16 +106,19 @@ struct windows_private_thread_info : private_thread_info, windows_thread_info
   {}
 };
 
-/* Get the windows_thread_info object associated with THR.  */
+/* If THR belongs to the windows-nat target, returns the
+   windows_thread_info object associated with it.  Otherwise returns
+   NULL.  */
 
 static inline windows_thread_info *
 as_windows_thread_info (thread_info *thr)
 {
   /* Cast to windows_private_thread_info, which inherits from
-     private_thread_info, and is implicitly convertible to
-     windows_thread_info, the return type.  */
+     windows_thread_info, the return type.  We use dynamic_cast,
+     because the inferior's thread list may have threads from other
+     targets on the target stack.  */
   private_thread_info *priv = thr->priv.get ();
-  return gdb::checked_static_cast<windows_private_thread_info *> (priv);
+  return dynamic_cast<windows_private_thread_info *> (priv);
 }
 
 struct windows_per_inferior : public windows_nat::windows_process_info
@@ -440,7 +443,7 @@ class all_windows_threads_iterator
 
   all_windows_threads_iterator &operator++ ()
   {
-    ++m_base_iter;
+    advance ();
     return *this;
   }
 
@@ -451,6 +454,9 @@ class all_windows_threads_iterator
   { return !(*this == other); }
 
 private:
+  /* Advance to the next windows-nat thread.  */
+  void advance ();
+
   all_non_exited_threads_iterator m_base_iter;
 };
 
@@ -463,8 +469,7 @@ class all_windows_threads_range : public all_non_exited_threads_range
     : m_base_range (base_range)
   {}
 
-  all_windows_threads_iterator begin () const
-  { return all_windows_threads_iterator (m_base_range.begin ()); }
+  all_windows_threads_iterator begin () const;
   all_windows_threads_iterator end () const
   { return all_windows_threads_iterator (m_base_range.end ()); }
 

base-commit: fd3cf86c638b7fdc0ccb64e178ec43ccd7e9d3f9
-- 
2.54.0


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-06-19 16:38 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-19 16:38 [PATCH] gdb/Windows: Make windows-nat skip iterating GPU threads Pedro Alves

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