Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Pedro Alves <pedro_alves@portugalmail.pt>
To: gdb-patches@sourceware.org, Lerele <lerele@champenstudios.com>
Subject: [gdbserver/win32] (4/11) New interrupting method
Date: Mon, 12 Nov 2007 02:07:00 -0000	[thread overview]
Message-ID: <4737B553.2040302@portugalmail.pt> (raw)

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

Hi,

Here is the new method to stop the inferior, based on a mix of
Leo's and mine patches.  The idea is simple.  Loop through all
the inferior threads suspending them.

This version doesn't contain the gdbserver priority handling,
which means that there is a higher chance of the inferior
breaking the method, since the operation is not atomic.  For
example by tweaking its own thread's priorities or if the
inferior is calling ResumeThread in its own threads while
gdbserver is stopping them.

The next patch will minimize those chances, by elevating
gdbserver's priority while stopping the inferior with
this method.

Leo, did I miss anything?

Regtested on a local i686-pc-cygwin gdbserver.

Cheers,
Pedro Alves





[-- Attachment #2: soft_interrupt.diff --]
[-- Type: text/x-diff, Size: 5704 bytes --]

2007-11-12  Leo Zayas  <lerele@champenstudios@com>
	    Pedro Alves  <pedro_alves@portugalmail.pt>

	* win32-low.c (soft_interrupt_requested, faked_breakpoint): New
	global variables.
	(child_add_thread): Minor cleanup.
	(child_continue): Resume artificially suspended threads before
	calling ContinueDebugEvent.
	(suspend_one_thread): New.
	(fake_breakpoint_event): New.
	(get_child_debug_event): Change return type to int.  Check here if
	gdb sent an interrupt request.  If a soft interrupt was
	requested, fake a breakpoint event.  Return 0 if there is no event
	to handle, and 1 otherwise.
	(win32_wait): Don't check here if gdb sent an interrupt request.
	Ensure there is a valid event to handle.
	(win32_request_interrupt): Add soft interruption method as last resort.

---
 gdb/gdbserver/win32-low.c |  100 ++++++++++++++++++++++++++++++++++++----------
 1 file changed, 79 insertions(+), 21 deletions(-)

Index: src/gdb/gdbserver/win32-low.c
===================================================================
--- src.orig/gdb/gdbserver/win32-low.c	2007-11-11 23:15:40.000000000 +0000
+++ src/gdb/gdbserver/win32-low.c	2007-11-11 23:15:44.000000000 +0000
@@ -72,6 +72,14 @@ static enum target_signal last_sig = TAR
 /* The current debug event from WaitForDebugEvent.  */
 static DEBUG_EVENT current_event;
 
+/* Non zero if an interrupt request is to be satisfied by suspending
+   all threads.  */
+static int soft_interrupt_requested = 0;
+
+/* Non zero if the inferior is stopped in a simulated breakpoint done
+   by suspending all the threads.  */
+static int faked_breakpoint = 0;
+
 #define NUM_REGS (the_low_target.num_regs)
 
 typedef BOOL WINAPI (*winapi_DebugActiveProcessStop) (DWORD dwProcessId);
@@ -134,8 +142,7 @@ child_add_thread (DWORD tid, HANDLE h)
   if ((th = thread_rec (tid, FALSE)))
     return th;
 
-  th = (win32_thread_info *) malloc (sizeof (*th));
-  memset (th, 0, sizeof (*th));
+  th = calloc (1, sizeof (*th));
   th->tid = tid;
   th->h = h;
 
@@ -293,14 +300,17 @@ continue_one_thread (struct inferior_lis
 static BOOL
 child_continue (DWORD continue_status, int thread_id)
 {
-  BOOL res;
-
-  res = ContinueDebugEvent (current_event.dwProcessId,
-			    current_event.dwThreadId, continue_status);
-  if (res)
-    find_inferior (&all_threads, continue_one_thread, &thread_id);
+  /* The inferior will only continue after the ContinueDebugEvent
+     call.  */
+  find_inferior (&all_threads, continue_one_thread, &thread_id);
+  faked_breakpoint = 0;
+
+  if (!ContinueDebugEvent (current_event.dwProcessId,
+			   current_event.dwThreadId,
+			   continue_status))
+    return FALSE;
 
-  return res;
+  return TRUE;
 }
 
 /* Fetch register(s) from the current thread context.  */
@@ -1247,19 +1257,67 @@ handle_exception (struct target_waitstat
   last_sig = ourstatus->value.sig;
 }
 
-/* Get the next event from the child.  */
+
 static void
-get_child_debug_event (struct target_waitstatus *ourstatus)
+suspend_one_thread (struct inferior_list_entry *entry)
+{
+  struct thread_info *thread = (struct thread_info *) entry;
+  win32_thread_info *th = inferior_target_data (thread);
+
+  if (!th->suspended)
+    {
+      if (SuspendThread (th->h) == (DWORD) -1)
+	{
+	  DWORD err = GetLastError ();
+	  OUTMSG (("warning: SuspendThread failed in suspend_one_thread, "
+		   "(error %d): %s\n", (int) err, strwinerror (err)));
+	}
+      else
+	th->suspended = 1;
+    }
+}
+
+static void
+fake_breakpoint_event (void)
 {
-  BOOL debug_event;
+  OUTMSG2(("fake_breakpoint_event\n"));
 
+  faked_breakpoint = 1;
+
+  memset (&current_event, 0, sizeof (current_event));
+  current_event.dwThreadId = main_thread_id;
+  current_event.dwDebugEventCode = EXCEPTION_DEBUG_EVENT;
+  current_event.u.Exception.ExceptionRecord.ExceptionCode =
+    EXCEPTION_BREAKPOINT;
+
+  for_each_inferior (&all_threads, suspend_one_thread);
+}
+
+/* Get the next event from the child.  */
+
+static int
+get_child_debug_event (struct target_waitstatus *ourstatus)
+{
   last_sig = TARGET_SIGNAL_0;
   ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
 
-  /* Keep the wait time low enough for confortable remote interruption,
-     but high enough so gdbserver doesn't become a bottleneck.  */
-  if (!(debug_event = WaitForDebugEvent (&current_event, 250)))
-    return;
+  /* Check if GDB sent us an interrupt request.  */
+  check_remote_input_interrupt_request ();
+
+  if (soft_interrupt_requested)
+    {
+      soft_interrupt_requested = 0;
+      fake_breakpoint_event ();
+      goto gotevent;
+    }
+
+  /* Keep the wait time low enough for confortable remote
+     interruption, but high enough so gdbserver doesn't become a
+     bottleneck.  */
+  if (!WaitForDebugEvent (&current_event, 250))
+    return 0;
+
+ gotevent:
 
   current_inferior =
     (struct thread_info *) find_inferior_id (&all_threads,
@@ -1376,6 +1434,7 @@ get_child_debug_event (struct target_wai
   current_inferior =
     (struct thread_info *) find_inferior_id (&all_threads,
 					     current_event.dwThreadId);
+  return 1;
 }
 
 /* Wait for the inferior process to change state.
@@ -1390,10 +1449,8 @@ win32_wait (char *status)
 
   while (1)
     {
-      /* Check if GDB sent us an interrupt request.  */
-      check_remote_input_interrupt_request ();
-
-      get_child_debug_event (&our_status);
+      if (!get_child_debug_event (&our_status))
+	continue;
 
       switch (our_status.kind)
 	{
@@ -1500,7 +1557,8 @@ win32_request_interrupt (void)
       && DebugBreakProcess (current_process_handle))
     return;
 
-  OUTMSG (("Could not interrupt process.\n"));
+  /* Last resort, suspend all threads manually.  */
+  soft_interrupt_requested = 1;
 }
 
 static const char *





             reply	other threads:[~2007-11-12  2:07 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-11-12  2:07 Pedro Alves [this message]
2007-11-25 15:00 ` Lerele
2007-11-25 18:47   ` Pedro Alves
2007-11-25 20:39     ` Lerele
2007-12-01 18:56 ` Daniel Jacobowitz
2007-12-03  3:53   ` 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=4737B553.2040302@portugalmail.pt \
    --to=pedro_alves@portugalmail.pt \
    --cc=gdb-patches@sourceware.org \
    --cc=lerele@champenstudios.com \
    /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