This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[gdbserver/wince] (7/11) Make the new interrupt method actually always work in WinCE


Hi,

The new method to interrupt the inferior should work
on WinCE.

Surprisingly, when writing my first version of the interrupt
support patch, a few months ago, I noticed that very frequently
the inferior would just crash.  I could see that I was
always stopping inside a kernel call when it crashed.  After a
few nights of severe head banging, I noticed that I could
reproduce it with Microsoft's debugger, by simply touching
any register value before resuming.  Even if I didn't
change the value, that is, I set the same value as what
was already in the register, I would get an exact same crash.

So, what I can get from this, is that, unfortunatelly, a
SuspendThread call doesn't suspend the thread immediatelly.
Well, that is actually documented, but what isn't clear from
MSDN is that the SuspendThread call actually returns without
error in that case.  In the case that the thread is still
doing something on the kernel side, after the
SuspendThread call, the results of  calling GetThreadContext
will reflect the fact that the thread was still running.
To be clear:

DWORD suspend_count = SuspendThread (h);

(check that is doesn't return with error)

GetThreadContext (h, &context);
Sleep (1000);
GetThreadContext (h, &context); /* may return something different */
Sleep (1000);
GetThreadContext (h, &context); /* may return something different */
Sleep (1000);

Unfortunatelly, there is no way to know if the thread is finally
stopped.

Fortunatelly, I found that there is a register key that makes
the Microsoft's debugger spit a few interesting logs.  And there
it was.  There is no SetThreadContext call being done when resuming
the inferior, unless we force the context to change in the
register window.

So, what this patch does, is implement the same workaround MSFT's
debugger uses.  Don't set the context back to the inferior, unless
it has been explicitly changed by gdb or gdbserver.  Actually, it
is a little bit better, as it won't crash if the user sets some
register's contents back to what it was when the inferior stopped.

Cheers,
Pedro Alves


2007-11-12  Pedro Alves  <pedro_alves@portugalmail.pt>

	* win32-low.c (win32_get_thread_context)
	(win32_set_thread_context): New.
	(thread_rec): Use win32_get_thread_context.
	(continue_one_thread, win32_resume): Use win32_set_thread_context.
	* win32-low.h (win32_thread_info) [_WIN32_WCE]: Add `base_context'
	field.

---
 gdb/gdbserver/win32-low.c |   39 ++++++++++++++++++++++++++++++++++++---
 gdb/gdbserver/win32-low.h |    7 ++++++-
 2 files changed, 42 insertions(+), 4 deletions(-)

Index: src/gdb/gdbserver/win32-low.c
===================================================================
--- src.orig/gdb/gdbserver/win32-low.c	2007-11-11 23:15:54.000000000 +0000
+++ src/gdb/gdbserver/win32-low.c	2007-11-11 23:16:02.000000000 +0000
@@ -100,6 +100,39 @@ current_inferior_tid (void)
   return th->tid;
 }
 
+/* Get the thread context of the thread associated with TH.  */
+
+static void
+win32_get_thread_context (win32_thread_info *th)
+{
+  memset (&th->context, 0, sizeof (CONTEXT));
+  (*the_low_target.get_thread_context) (th, &current_event);
+#ifdef _WIN32_WCE
+  memcpy (&th->base_context, &th->context, sizeof (CONTEXT));
+#endif
+}
+
+/* Set the thread context of the thread associated with TH.  */
+
+static void
+win32_set_thread_context (win32_thread_info *th)
+{
+#ifdef _WIN32_WCE
+  /* Calling SuspendThread on a thread that is running kernel code
+     will report that the suspending was successful, but in fact, that
+     will often not be true.  In those cases, the context returned by
+     GetThreadContext will not be correct by the time the thread
+     stops, hence we can't set that context back into the thread when
+     resuming - it will most likelly crash the inferior.
+     Unfortunately, there is no way to know when the thread will
+     really stop.  To work around it, we'll only write the context
+     back to the thread when either the user or GDB explicitly change
+     it between stopping and resuming.  */
+  if (memcmp (&th->context, &th->base_context, sizeof (CONTEXT)) != 0)
+#endif
+    (*the_low_target.set_thread_context) (th, &current_event);
+}
+
 /* Find a thread record given a thread id.  If GET_CONTEXT is set then
    also retrieve the context for this thread.  */
 static win32_thread_info *
@@ -127,7 +160,7 @@ thread_rec (DWORD id, int get_context)
 	    th->suspended = 1;
 	}
 
-      (*the_low_target.get_thread_context) (th, &current_event);
+      win32_get_thread_context (th);
     }
 
   return th;
@@ -434,7 +467,7 @@ continue_one_thread (struct inferior_lis
     {
       if (th->context.ContextFlags)
 	{
-	  (*the_low_target.set_thread_context) (th, &current_event);
+	  win32_set_thread_context (th);
 	  th->context.ContextFlags = 0;
 	}
 
@@ -978,7 +1011,7 @@ win32_resume (struct thread_resume *resu
 		       "in this configuration.\n");
 	    }
 
-	  (*the_low_target.set_thread_context) (th, &current_event);
+	  win32_set_thread_context (th);
 	  th->context.ContextFlags = 0;
 	}
     }
Index: src/gdb/gdbserver/win32-low.h
===================================================================
--- src.orig/gdb/gdbserver/win32-low.h	2007-11-11 23:15:40.000000000 +0000
+++ src/gdb/gdbserver/win32-low.h	2007-11-11 23:16:02.000000000 +0000
@@ -31,7 +31,12 @@ typedef struct win32_thread_info
   /* Non zero if SuspendThread was called on this thread.  */
   int suspended;
 
-  /* The context of the thread.  */
+#ifdef _WIN32_WCE
+  /* The context as retrieved right after suspending the thread. */
+  CONTEXT base_context;
+#endif
+
+  /* The context of the thread, including any manipulations.  */
   CONTEXT context;
 } win32_thread_info;
 






Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]