Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Pedro Alves <pedro@palves.net>
To: gdb-patches@sourceware.org
Subject: [PATCH] Windows gdb: all-stop, interrupt with "stopped" instead of SIGTRAP
Date: Tue,  5 May 2026 13:24:33 +0100	[thread overview]
Message-ID: <20260505122434.1444507-1-pedro@palves.net> (raw)

Currently, "interrupt" uses DebugBreakProcess (or equivalent), which
injects a new thread in the inferior that executes an int3 instruction
(on x86), which raises a SIGTRAP.  With the target backend in non-stop
mode, its easy to avoid all that and make interrupt in all-stop just
suspend a pre-existing thread and report "stopped", like "set non-stop
on" does (via target_stop).

E.g., before:

 (gdb) c&
 Continuing.
 ...
 (gdb) info threads
   Id   Target Id          Frame
 * 1    Thread 1180.0x1374 (running)
   2    Thread 1180.0xc3c  (running)
   3    Thread 1180.0x6ec  (running)
   5    Thread 1180.0x1378 (running)
 (gdb)
 ...
 [New Thread 1180.0xc70]
 [Thread 1180.0x1378 exited with code 0]
 [Thread 1180.0xc70 exited with code 0]
 [New Thread 1180.0xdc0]
 ...
 interrupt
 (gdb) [New Thread 1180.0x1010]

 Thread 8 received signal SIGTRAP, Trace/breakpoint trap.
 [Switching to Thread 1180.0x1010]
 0x00007ffa57490b71 in ntdll!DbgBreakPoint () from C:\Windows\SYSTEM32\ntdll.dll
 info threads
   Id   Target Id          Frame
   1    Thread 1180.0x1374 0x00007ffa5748d6e4 in ntdll!ZwDelayExecution () from C:\Windows\SYSTEM32\ntdll.dll
   2    Thread 1180.0xc3c  0x00007ffa57490ad4 in ntdll!ZwWaitForWorkViaWorkerFactory () from C:\Windows\SYSTEM32\ntdll.dll
   3    Thread 1180.0x6ec  0x00007ffa5748d6e4 in ntdll!ZwDelayExecution () from C:\Windows\SYSTEM32\ntdll.dll
   7    Thread 1180.0xdc0  0x00007ffa5748d6e4 in ntdll!ZwDelayExecution () from C:\Windows\SYSTEM32\ntdll.dll
 * 8    Thread 1180.0x1010 0x00007ffa57490b71 in ntdll!DbgBreakPoint () from C:\Windows\SYSTEM32\ntdll.dll
 (gdb)

After:

 (gdb) info threads
   Id   Target Id          Frame
 * 1    Thread 5912.0x394  (running)
   2    Thread 5912.0x608  (running)
   3    Thread 5912.0x1704 (running)
   10   Thread 5912.0x870  (running)
 (gdb)
 ...
 [Thread 5912.0x870 exited with code 0]
 ...
 (gdb) interrupt
 (gdb)
 Thread 1 stopped.
 0x00007ffa5748d6e4 in ntdll!ZwDelayExecution () from C:\Windows\SYSTEM32\ntdll.dll
 info threads
   Id   Target Id          Frame
 * 1    Thread 5912.0x394  0x00007ffa5748d6e4 in ntdll!ZwDelayExecution () from C:\Windows\SYSTEM32\ntdll.dll
   2    Thread 5912.0x608  0x00007ffa57490ad4 in ntdll!ZwWaitForWorkViaWorkerFactory () from C:\Windows\SYSTEM32\ntdll.dll
   3    Thread 5912.0x1704 0x00007ffa5748d6e4 in ntdll!ZwDelayExecution () from C:\Windows\SYSTEM32\ntdll.dll
   8    Thread 5912.0x1200 0x00007ffa5748d6e4 in ntdll!ZwDelayExecution () from C:\Windows\SYSTEM32\ntdll.dll
 (gdb)

Change-Id: I569fc69392ce9a070a2ebe1003388b7386412b14
commit-id: 8f6b76d2
---
 gdb/windows-nat.c | 68 +++++++++++++++++++++++++++++++++++++++--------
 gdb/windows-nat.h |  5 +++-
 2 files changed, 61 insertions(+), 12 deletions(-)

diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index a9647e90bb8..b9d32b6c0c4 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -1177,6 +1177,30 @@ void
 windows_nat_target::interrupt ()
 {
   DEBUG_EVENTS ("interrupt");
+
+  if (target_is_non_stop_p ())
+    {
+      /* Since we have finer-grained control and can suspend threads,
+	 we can report a "stopped" event for an existing thread,
+	 instead of force-injecting a new thread that reports SIGTRAP
+	 with DebugBreakProcess.
+
+	 Stop one thread, any thread.  */
+      stop_interrupt (minus_one_ptid, true);
+      return;
+    }
+
+  if (!dbg_break_process ())
+    warning (_("Could not interrupt program.  "
+	       "Press Ctrl-c in the program console."));
+}
+
+/* Stop the process with DebugBreakProcess or equivalent.  Return true
+   on success, false otherwise.  */
+
+bool
+windows_nat_target::dbg_break_process ()
+{
 #ifdef __x86_64__
   if (windows_process->wow64_process)
     {
@@ -1200,23 +1224,25 @@ windows_nat_target::interrupt ()
 	  if (thread)
 	    {
 	      CloseHandle (thread);
-	      return;
+	      return true;
 	    }
 	}
     }
   else
 #endif
     if (DebugBreakProcess (windows_process->handle))
-      return;
-  warning (_("Could not interrupt program.  "
-	     "Press Ctrl-c in the program console."));
+      return true;
+
+  return false;
 }
 
 /* Stop thread TH, for STOPPING_KIND reason.  This leaves a
    GDB_SIGNAL_0 pending in the thread, which is later consumed by
-   windows_nat_target::wait.  */
+   windows_nat_target::wait.  Return true if TH gets suspended and now
+   has a new stop event to report; false if TH was already suspended
+   and has no new stop event.  */
 
-void
+bool
 windows_nat_target::stop_one_thread (windows_thread_info *th,
 				     enum stopping_kind stopping_kind)
 {
@@ -1230,6 +1256,7 @@ windows_nat_target::stop_one_thread (windows_thread_info *th,
       DEBUG_EVENTS ("already suspended %s: suspended=%d, stopping=%d",
 		    thr_ptid.to_string ().c_str (),
 		    th->suspended, th->stopping);
+      return false;
     }
 #ifdef __CYGWIN__
   else if (th->suspended
@@ -1249,6 +1276,7 @@ windows_nat_target::stop_one_thread (windows_thread_info *th,
       th->pending_status.set_stopped (GDB_SIGNAL_0);
       th->last_event = {};
       serial_event_set (m_wait_event);
+      return true;
     }
 #endif
   else if (th->suspended)
@@ -1262,6 +1290,7 @@ windows_nat_target::stop_one_thread (windows_thread_info *th,
       /* Upgrade stopping.  */
       if (stopping_kind > th->stopping)
 	th->stopping = stopping_kind;
+      return false;
     }
   else
     {
@@ -1278,7 +1307,7 @@ windows_nat_target::stop_one_thread (windows_thread_info *th,
 			thr_ptid.to_string ().c_str ());
 	  if (stopping_kind > th->stopping)
 	    th->stopping = stopping_kind;
-	  return;
+	  return false;
 	}
 
       gdb_assert (th->suspended == 1);
@@ -1291,21 +1320,38 @@ windows_nat_target::stop_one_thread (windows_thread_info *th,
 	}
 
       serial_event_set (m_wait_event);
+      return true;
     }
 }
 
-/* Implementation of target_ops::stop.  */
+/* Helper for windows_nat_target::stop and
+   windows_nat_target::interrupt.  Stops PTID.  If STOP_ON_FIRST_MATCH
+   is true, returns immediately as soon as one thread is stopped.  */
 
 void
-windows_nat_target::stop (ptid_t ptid)
+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))
-	stop_one_thread (as_windows_thread_info (&thr), SK_EXTERNAL);
+      if (!thr.ptid.matches (ptid))
+	continue;
+
+      if (stop_one_thread (as_windows_thread_info (&thr), SK_EXTERNAL))
+	{
+	  if (stop_on_first_match)
+	    return;
+	}
     }
 }
 
+/* Implementation of target_ops::stop.  */
+
+void
+windows_nat_target::stop (ptid_t ptid)
+{
+  stop_interrupt (ptid, false);
+}
+
 void
 windows_nat_target::pass_ctrlc ()
 {
diff --git a/gdb/windows-nat.h b/gdb/windows-nat.h
index 1f7ecb07e4f..8e6e79a8160 100644
--- a/gdb/windows-nat.h
+++ b/gdb/windows-nat.h
@@ -312,9 +312,12 @@ struct windows_nat_target : public inf_child_target
   void delete_thread (ptid_t ptid, DWORD exit_code, bool main_thread_p);
   DWORD fake_create_process (const DEBUG_EVENT &current_event);
 
-  void stop_one_thread (windows_thread_info *th,
+  bool stop_one_thread (windows_thread_info *th,
 			enum windows_nat::stopping_kind stopping_kind);
 
+  void stop_interrupt (ptid_t ptid, bool stop_on_first_match);
+  bool dbg_break_process ();
+
   DWORD continue_status_for_event_detaching
     (const DEBUG_EVENT &event, size_t *reply_later_events_left = nullptr);
 

base-commit: 297fe552edd546e4fe9f47c7a0765a55ce084f0c
-- 
2.53.0


             reply	other threads:[~2026-05-05 12:25 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-05 12:24 Pedro Alves [this message]
2026-05-05 14:17 ` Tom Tromey
2026-05-07 18:44   ` Pedro Alves

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260505122434.1444507-1-pedro@palves.net \
    --to=pedro@palves.net \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox