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]

[RFC-v3] win32-nat.c 'set new-console' and interruption


> >So, I would personally prefered if we kept the SIGTRAP to SIGINT
> >translation... Just my 2 cents.
> 
> I think that makes 4 cents.  A SIGTRAP would be confusing.
> 
> I haven't looked at the patch yet, however.
> 
> cgf

In that case, let me send you a new version of the patch then:
version 3 superseeds the two previous versions in this thread.

 It contains the attempt to distinguish
if EXCEPTION_BREAKPOINT comes from the win32_stop call,
to eliminate the race condition you raised:
if ctrl_break_sent is set and the location of the 
exception addr is not a breakpoint set by GDB,
then we assume that the exception was generated by
the call to DebugBreakProcess.

  I also added code to reset ctrl_break_sent to zero 
in do_initial_win32_stuff.

  Finally I also set start_flags to CREATE_NEW_CONSOLE
if we attach to a running process rather than
start one. It seems rather odd to me to try to
attach to a process running in the same console, it
is much better to start GDB in an new console and
to attach from there.
  Nevertheless, I must admit that I don't know if
there is away to know if the process to which we are attaching
is running in the console or not.


Pierre Muller
Pascal language support maintainer for GDB


$ cat win32term.log
ChangeLog entry:

2008-06-24  Pierre Muller  <muller@ics.u-strasbg.fr>

        * win32-nat.c (group_id, ctrl_break_sent, start_flags): New
variables.
        (handle_exception): Recognize signal sent with DebugBreakProcess
        and treat as TARGET_SIGNAL_INT.
        (gdb_ctrl_handler): New function. Sends a interrupting signal to
        debuggee.
        (win32_wait): Use gdb_ctrl_handler if debuggee started in a new
console.
        (do_initial_win32_stuff): Reset ctrl_break_sent.
        (kernel32): HANDLE variable moved from has_detach_ability to main
level.
        (win32_attach): set start_flags to CREATE_NEW_CONSOLE.
        (DebugBreakProcess): New function variable.
        (win32_stop): Only use GenerateConsoleCtrlEvent if debuggee on same
        console. Otherwise test for kernel32 DebugBreakProcess function and
        use if available.
        (win32_create_inferior): Set start_flags and group_id.
        (win32_terminal_inferior, win32_terminal_ours): New functions.
        Do nothing if debuggee was started in a new console.
        (win32_terminal_ours_for_output): New function, as above.
        (init_win32_ops): Set to_terminal_inferior to
win32_terminal_inferior
        and to_terminal_ours to win32_terminal_ours.


$ cat  win32term.patch
Index: gdb/win32-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/win32-nat.c,v
retrieving revision 1.155
diff -u -p -r1.155 win32-nat.c
--- gdb/win32-nat.c     24 Jun 2008 02:33:17 -0000      1.155
+++ gdb/win32-nat.c     24 Jun 2008 07:43:13 -0000
@@ -137,6 +137,8 @@ static DEBUG_EVENT current_event;   /* The
 static HANDLE current_process_handle;  /* Currently executing process */
 static thread_info *current_thread;    /* Info on currently selected thread
*/
 static DWORD main_thread_id;           /* Thread ID of the main thread */
+static DWORD group_id = 0;
+static int ctrl_break_sent = 0;

 /* Counts of things. */
 static int exception_count = 0;
@@ -155,6 +157,7 @@ static int debug_events = 0;                /* show ev
 static int debug_memory = 0;           /* show target memory accesses */
 static int debug_exceptions = 0;       /* show target exceptions */
 static int useshell = 0;               /* use shell for subprocesses */
+static DWORD start_flags = 0;          /* remember CreateProcess flags */

 /* This vector maps GDB's idea of a register's number into an address
    in the win32 exception context vector.
@@ -1074,7 +1077,22 @@ handle_exception (struct target_waitstat
       break;
     case EXCEPTION_BREAKPOINT:
       DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
-      ourstatus->value.sig = TARGET_SIGNAL_TRAP;
+      if (ctrl_break_sent)
+
+       {
+          CORE_ADDR addr =
+           (CORE_ADDR)
current_event.u.Exception.ExceptionRecord.ExceptionAddre
ss;
+
+          if (!breakpoint_inserted_here_p (addr))
+           {
+             DEBUG_EXCEPT (("EXCEPTION_BREAKPOINT at 0x%lx converted to \
+TARGET_SIGNAL_INT\n", (DWORD) addr));
+             ctrl_break_sent = 0;
+             ourstatus->value.sig = TARGET_SIGNAL_INT;
+           }
+       }
+      else
+       ourstatus->value.sig = TARGET_SIGNAL_TRAP;
       break;
     case DBG_CONTROL_C:
       DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_C");
@@ -1445,6 +1463,30 @@ out:
   return retval;
 }

+
+static BOOL WINAPI
+gdb_ctrl_handler (DWORD dw_ctrl_type)
+{
+  DEBUG_EVENTS(("gdb_ctrl_handler called with dwCtrType=%u\n",
+               (unsigned int) dw_ctrl_type));
+  switch (dw_ctrl_type)
+    {
+      case CTRL_C_EVENT:
+      case CTRL_BREAK_EVENT:
+       win32_stop();
+       /* Notify that event is handled.  */
+       return TRUE;
+       break;
+      case CTRL_CLOSE_EVENT:
+      case CTRL_LOGOFF_EVENT:
+      case CTRL_SHUTDOWN_EVENT:
+       /* Notify that event is not handled.  */
+       return FALSE;
+        break;
+   }
+  return FALSE;
+}
+
 /* Wait for interesting events to occur in the target process. */
 static ptid_t
 win32_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
@@ -1476,9 +1518,16 @@ win32_wait (ptid_t ptid, struct target_w
          in the inferior.  This is a classic race, and it would be nice
          to find a better solution to that problem.  But in the meantime,
          the current approach already greatly mitigate this issue.  */
-      SetConsoleCtrlHandler (NULL, TRUE);
+      if (start_flags & CREATE_NEW_CONSOLE)
+       SetConsoleCtrlHandler (&gdb_ctrl_handler, TRUE);
+      else
+       SetConsoleCtrlHandler (NULL, TRUE);
       retval = get_win32_debug_event (pid, ourstatus);
       SetConsoleCtrlHandler (NULL, FALSE);
+      if (start_flags & CREATE_NEW_CONSOLE)
+       SetConsoleCtrlHandler (&gdb_ctrl_handler, FALSE);
+      else
+       SetConsoleCtrlHandler (NULL, FALSE);

       if (retval)
        return pid_to_ptid (retval);
@@ -1505,6 +1554,8 @@ do_initial_win32_stuff (DWORD pid)
   event_count = 0;
   exception_count = 0;
   open_process_used = 0;
+  ctrl_break_sent = 0;
+
   debug_registers_changed = 0;
   debug_registers_used = 0;
   for (i = 0; i < sizeof (dr) / sizeof (dr[0]); i++)
@@ -1546,12 +1597,12 @@ do_initial_win32_stuff (DWORD pid)
    detach has worked. */
 static BOOL WINAPI (*DebugSetProcessKillOnExit)(BOOL);
 static BOOL WINAPI (*DebugActiveProcessStop)(DWORD);
-
+static BOOL WINAPI (*DebugBreakProcess)(HANDLE);
+static HMODULE kernel32 = NULL;
+
 static int
 has_detach_ability (void)
 {
-  static HMODULE kernel32 = NULL;
-
   if (!kernel32)
     kernel32 = LoadLibrary ("kernel32.dll");
   if (kernel32)
@@ -1686,6 +1737,10 @@ win32_attach (char *args, int from_tty)

   attach_flag = 1;

+  /* Attaching to a process on the same console seems not the right thing
to do
.
+     Let's assume the debuggee runs on a separate console.  */
+  start_flags = CREATE_NEW_CONSOLE;
+
   if (from_tty)
     {
       char *exec_file = (char *) get_exec_file (0);
@@ -1906,6 +1961,13 @@ win32_create_inferior (char *exec_file,
   else
     saw_create = 0;

+  start_flags = flags;
+
+  if (flags & CREATE_NEW_PROCESS_GROUP)
+    group_id = pi.dwProcessId;
+  else
+    group_id = 0;
+
   do_initial_win32_stuff (pi.dwProcessId);

   /* win32_continue (DBG_CONTINUE, -1); */
@@ -1921,6 +1983,7 @@ win32_mourn_inferior (void)
       CHECK (CloseHandle (current_process_handle));
       open_process_used = 0;
     }
+  start_flags = 0;
   unpush_target (&win32_ops);
   generic_mourn_inferior ();
 }
@@ -1931,11 +1994,35 @@ win32_mourn_inferior (void)
 static void
 win32_stop (void)
 {
-  DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n"));
-  CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT,
current_event.dwProcessId));
+  if ((start_flags & CREATE_NEW_CONSOLE) == 0)
+    {
+      DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT,
%lu)\n",

+                   current_event.dwProcessId));
+      CHECK (GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT,
+                                      group_id));
+    }
+  else
+    {
+      if (!kernel32)
+       kernel32 = LoadLibrary ("kernel32.dll");
+      if (kernel32)
+       {
+         if (!DebugBreakProcess)
+           DebugBreakProcess = GetProcAddress (kernel32,
"DebugBreakProcess");
+       }
+      if (DebugBreakProcess && current_process_handle)
+       {
+         DEBUG_EVENTS (("DebugBreakProcess (%d)\n",
+                        (int) current_process_handle));
+         ctrl_break_sent = 1;
+         DebugBreakProcess (current_process_handle);
+       }
+      else
+        DEBUG_EVENTS (("Unable to interrupt debuggee in another
console\n"));
+    }
   registers_changed ();                /* refresh register state */
 }
-
+
 static int
 win32_xfer_memory (CORE_ADDR memaddr, gdb_byte *our, int len,
                   int write, struct mem_attrib *mem,
@@ -2076,6 +2163,36 @@ win32_xfer_partial (struct target_ops *o
       return -1;
     }
 }
+static void
+win32_terminal_inferior ()
+{
+  /* If the debuggee is not on the same console,
+     we don't need to do anything.  */
+  if (start_flags & CREATE_NEW_CONSOLE)
+    return;
+  terminal_inferior ();
+}
+
+static void
+win32_terminal_ours_for_output ()
+{
+  /* If the debuggee is not on the same console,
+     we don't need to do anything.  */
+  if (start_flags & CREATE_NEW_CONSOLE)
+    return;
+  terminal_ours_for_output ();
+}
+
+
+static void
+win32_terminal_ours ()
+{
+  /* If the debuggee is not on the same console,
+     we don't need to do anything.  */
+  if (start_flags & CREATE_NEW_CONSOLE)
+    return;
+  terminal_ours ();
+}

 static void
 init_win32_ops (void)
@@ -2098,9 +2215,9 @@ init_win32_ops (void)
   win32_ops.to_insert_breakpoint = memory_insert_breakpoint;
   win32_ops.to_remove_breakpoint = memory_remove_breakpoint;
   win32_ops.to_terminal_init = terminal_init_inferior;
-  win32_ops.to_terminal_inferior = terminal_inferior;
-  win32_ops.to_terminal_ours_for_output = terminal_ours_for_output;
-  win32_ops.to_terminal_ours = terminal_ours;
+  win32_ops.to_terminal_inferior = win32_terminal_inferior;
+  win32_ops.to_terminal_ours_for_output = win32_terminal_ours_for_output;
+  win32_ops.to_terminal_ours = win32_terminal_ours;
   win32_ops.to_terminal_save_ours = terminal_save_ours;
   win32_ops.to_terminal_info = child_terminal_info;
   win32_ops.to_kill = win32_kill_inferior;



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