* server.h (check_remote_input_interrupt_request): New function.
authorPedro Alves <palves@redhat.com>
Thu, 10 May 2007 22:04:50 +0000 (22:04 +0000)
committerPedro Alves <palves@redhat.com>
Thu, 10 May 2007 22:04:50 +0000 (22:04 +0000)
* remote_utils.c (INVALID_DESCRIPTOR): New define.
(remote_desc): Initialize with INVALID_DESCRIPTOR.
(input_interrupt): Expose on USE_WIN32API too.  Fix whitespace.
(check_remote_input_interrupt_request): New function.
* server.h (check_remote_input_interrupt_request): Declare.

* win32-low.(winapi_DebugBreakProcess,
winapi_GenerateConsoleCtrlEvent): New typedefs.
(get_child_debug_event): Lower Win32 debug event polling from 1 sec
to 250 ms.
(win32_wait): Check for remote interrupt request
with check_remote_input_interrupt_request.
(win32_request_interrupt): New function.
(win32_target_op): Set request_interrupt to win32_request_interrupt.

gdb/gdbserver/ChangeLog
gdb/gdbserver/remote-utils.c
gdb/gdbserver/server.h
gdb/gdbserver/win32-low.c

index 028da2e864f104e75d048c9eba2fa2c0d7cd70e4..4ccec232a4e89a11e68e47e47f6af21de179cc81 100644 (file)
@@ -1,3 +1,22 @@
+2007-05-10  Pedro Alves  <pedro_alves@portugalmail.pt>
+           Leo Zayas  <lerele@champenstudios@com>
+
+       * server.h (check_remote_input_interrupt_request): New function.
+       * remote_utils.c (INVALID_DESCRIPTOR): New define.
+       (remote_desc): Initialize with INVALID_DESCRIPTOR.
+       (input_interrupt): Expose on USE_WIN32API too.  Fix whitespace.
+       (check_remote_input_interrupt_request): New function.
+       * server.h (check_remote_input_interrupt_request): Declare.
+
+       * win32-low.(winapi_DebugBreakProcess,
+       winapi_GenerateConsoleCtrlEvent): New typedefs.
+       (get_child_debug_event): Lower Win32 debug event polling from 1 sec
+       to 250 ms.
+       (win32_wait): Check for remote interrupt request
+       with check_remote_input_interrupt_request.
+       (win32_request_interrupt): New function.
+       (win32_target_op): Set request_interrupt to win32_request_interrupt.
+
 2007-05-10  Pedro Alves  <pedro_alves@portugalmail.pt>
 
        * win32-low.c (debug_registers_changed,
index 3c0e5e47282a3af18aee92b8c942d78dc76b54d2..505e37c907d2f1847815de25f320cf967558c683 100644 (file)
 typedef int socklen_t;
 #endif
 
+#if USE_WIN32API
+# define INVALID_DESCRIPTOR INVALID_SOCKET
+#else
+# define INVALID_DESCRIPTOR -1
+#endif
+
 /* A cache entry for a successfully looked-up symbol.  */
 struct sym_cache
 {
@@ -88,7 +94,7 @@ int all_symbols_looked_up;
 int remote_debug = 0;
 struct ui_file *gdb_stdlog;
 
-static int remote_desc;
+static int remote_desc = INVALID_DESCRIPTOR;
 
 /* FIXME headerize? */
 extern int using_threads;
@@ -588,8 +594,6 @@ putpkt (char *buf)
   return putpkt_binary (buf, strlen (buf));
 }
 
-#ifndef USE_WIN32API
-
 /* Come here when we get an input interrupt from the remote side.  This
    interrupt should only be active while we are waiting for the child to do
    something.  About the only thing that should come through is a ^C, which
@@ -610,7 +614,7 @@ input_interrupt (int unused)
     {
       int cc;
       char c = 0;
-      
+
       cc = read (remote_desc, &c, 1);
 
       if (cc != 1 || c != '\003')
@@ -619,11 +623,23 @@ input_interrupt (int unused)
                   cc, c, c);
          return;
        }
-      
+
       (*the_target->request_interrupt) ();
     }
 }
-#endif
+
+/* Check if the remote side sent us an interrupt request (^C).  */
+void
+check_remote_input_interrupt_request (void)
+{
+  /* This function may be called before establishing communications,
+     therefore we need to validate the remote descriptor.  */
+
+  if (remote_desc == INVALID_DESCRIPTOR)
+    return;
+
+  input_interrupt (0);
+}
 
 /* Asynchronous I/O support.  SIGIO must be enabled when waiting, in order to
    accept Control-C from the client, and must be disabled when talking to
index d433f30837858dff067a407aea4efb245c7e80f9..b1ff238f4d6b873e5f396e0a8fb1bb173e5b6655 100644 (file)
@@ -161,6 +161,7 @@ void enable_async_io (void);
 void disable_async_io (void);
 void unblock_async_io (void);
 void block_async_io (void);
+void check_remote_input_interrupt_request (void);
 void convert_ascii_to_int (char *from, unsigned char *to, int n);
 void convert_int_to_ascii (unsigned char *from, char *to, int n);
 void new_thread_notify (int id);
index 51b1915ee8447d53da7352db61d3ff704abd3552..736d85e05b0aad0cfc855bbb48bb96ade50dd6e5 100644 (file)
@@ -77,6 +77,8 @@ static DEBUG_EVENT current_event;
 
 typedef BOOL WINAPI (*winapi_DebugActiveProcessStop) (DWORD dwProcessId);
 typedef BOOL WINAPI (*winapi_DebugSetProcessKillOnExit) (BOOL KillOnExit);
+typedef BOOL WINAPI (*winapi_DebugBreakProcess) (HANDLE);
+typedef BOOL WINAPI (*winapi_GenerateConsoleCtrlEvent) (DWORD, DWORD);
 
 static DWORD main_thread_id = 0;
 
@@ -208,9 +210,8 @@ enum target_waitkind
      pathname is pointed to by value.execd_pathname.  */
   TARGET_WAITKIND_EXECD,
 
-  /* Nothing happened, but we stopped anyway.  This perhaps should be handled
-     within target_wait, but I'm not sure target_wait should be resuming the
-     inferior.  */
+  /* Nothing interesting happened, but we stopped anyway.  We take the
+     chance to check if GDB requested an interrupt.  */
   TARGET_WAITKIND_SPURIOUS,
 };
 
@@ -879,7 +880,9 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
   last_sig = TARGET_SIGNAL_0;
   ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
 
-  if (!(debug_event = WaitForDebugEvent (&current_event, 1000)))
+  /* 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;
 
   current_inferior =
@@ -1007,6 +1010,9 @@ 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);
 
       switch (our_status.kind)
@@ -1078,6 +1084,39 @@ win32_write_inferior_memory (CORE_ADDR memaddr, const unsigned char *myaddr,
   return child_xfer_memory (memaddr, (char *) myaddr, len, 1, 0) != len;
 }
 
+/* Send an interrupt request to the inferior process. */
+static void
+win32_request_interrupt (void)
+{
+  winapi_DebugBreakProcess DebugBreakProcess;
+  winapi_GenerateConsoleCtrlEvent GenerateConsoleCtrlEvent;
+
+#ifdef _WIN32_WCE
+  HMODULE dll = GetModuleHandle (_T("COREDLL.DLL"));
+#else
+  HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
+#endif
+
+  GenerateConsoleCtrlEvent = GETPROCADDRESS (dll, GenerateConsoleCtrlEvent);
+
+  if (GenerateConsoleCtrlEvent != NULL
+      && GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, current_process_id))
+    return;
+
+  /* GenerateConsoleCtrlEvent can fail if process id being debugged is
+     not a process group id.
+     Fallback to XP/Vista 'DebugBreakProcess', which generates a
+     breakpoint exception in the interior process.  */
+
+  DebugBreakProcess = GETPROCADDRESS (dll, DebugBreakProcess);
+
+  if (DebugBreakProcess != NULL
+      && DebugBreakProcess (current_process_handle))
+    return;
+
+  OUTMSG (("Could not interrupt process.\n"));
+}
+
 static const char *
 win32_arch_string (void)
 {
@@ -1098,7 +1137,7 @@ static struct target_ops win32_target_ops = {
   win32_read_inferior_memory,
   win32_write_inferior_memory,
   NULL,
-  NULL,
+  win32_request_interrupt,
   NULL,
   NULL,
   NULL,