]> git.eshelyaron.com Git - emacs.git/commitdiff
Support SIGTRAP in kill emulation on Windows
authorAlain Schneble <a.s@realize.ch>
Sat, 8 Oct 2016 13:52:40 +0000 (16:52 +0300)
committerEli Zaretskii <eliz@gnu.org>
Sat, 8 Oct 2016 13:52:40 +0000 (16:52 +0300)
* src/w32proc.c (sys_kill): Translate SIGTRAP signal into a call to
'DebugBreakProcess' to cause a breakpoint exception to occur in the
specified process.  On Windows versions prior to Windows XP that do
not support 'DebugBreakProcess' return -1 and set errno to ENOTSUP
(as opposed to EINVAL before this change).
* src/w32proc.c: Add typedef for 'DebugBreakProcess' function pointer
and global variable to track state of run-time dynamic linking of this
function.

* etc/NEWS: Add entry to document that 'signal-process' now supports
SIGTRAP.

etc/NEWS
src/w32.c
src/w32proc.c

index 59fb72a2beceeac167b33bb275c3e0ddb8cbe29c..14450a6bbe5470346062773f6fbca98636b04062 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -668,6 +668,16 @@ session and exits.  In particular, this will happen if you start
 emacs.exe from the Windows shell, then type Ctrl-C into that shell's
 window.
 
+---
+** 'signal-process' supports SIGTRAP on Windows XP and later.
+The 'kill' emulation on Windows now maps SIGTRAP to a call to the
+'DebugBreakProcess' API.  This causes the receiving process to break
+execution and return control to the debugger.  If no debugger is
+attached to the receiving process, the call is typically ignored.
+This is in contrast to the default action on POSIX Systems, where it
+causes the receiving process to terminate with a core dump if no
+debugger has been attached to it.
+
 \f
 ----------------------------------------------------------------------
 This file is part of GNU Emacs.
index f9110853799f25a99730f6e64ad57f1b517e6121..517e286eaa903260af37d7f32d246b85c75fa963 100644 (file)
--- a/src/w32.c
+++ b/src/w32.c
@@ -334,6 +334,7 @@ static BOOL g_b_init_set_named_security_info_a;
 static BOOL g_b_init_get_adapters_info;
 
 BOOL g_b_init_compare_string_w;
+BOOL g_b_init_debug_break_process;
 
 /*
   BEGIN: Wrapper functions around OpenProcessToken
@@ -9657,6 +9658,7 @@ globals_of_w32 (void)
   g_b_init_set_named_security_info_a = 0;
   g_b_init_get_adapters_info = 0;
   g_b_init_compare_string_w = 0;
+  g_b_init_debug_break_process = 0;
   num_of_processors = 0;
   /* The following sets a handler for shutdown notifications for
      console apps. This actually applies to Emacs in both console and
index aef4e44d73a3568cfeb2b34164fa9e7ed3b9ba8f..189034c4e2d89215342bafb15b9ec4c38f04b406 100644 (file)
@@ -69,6 +69,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
            + (filedata).file_base))
 
 extern BOOL g_b_init_compare_string_w;
+extern BOOL g_b_init_debug_break_process;
+
 int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
                struct timespec *, void *);
 
@@ -2497,6 +2499,9 @@ find_child_console (HWND hwnd, LPARAM arg)
   return TRUE;
 }
 
+typedef BOOL (WINAPI * DebugBreakProcess_Proc) (
+    HANDLE hProcess);
+
 /* Emulate 'kill', but only for other processes.  */
 int
 sys_kill (pid_t pid, int sig)
@@ -2510,9 +2515,9 @@ sys_kill (pid_t pid, int sig)
   if (pid < 0)
     pid = -pid;
 
-  /* Only handle signals that will result in the process dying */
+  /* Only handle signals that can be mapped to a similar behavior on Windows */
   if (sig != 0
-      && sig != SIGINT && sig != SIGKILL && sig != SIGQUIT && sig != SIGHUP)
+      && sig != SIGINT && sig != SIGKILL && sig != SIGQUIT && sig != SIGHUP && sig != SIGTRAP)
     {
       errno = EINVAL;
       return -1;
@@ -2555,7 +2560,11 @@ sys_kill (pid_t pid, int sig)
         close the selected frame, which does not necessarily
         terminates Emacs.  But then we are not supposed to call
         sys_kill with our own PID.  */
-      proc_hand = OpenProcess (PROCESS_TERMINATE, 0, pid);
+
+      DWORD desiredAccess =
+       (sig == SIGTRAP) ? PROCESS_ALL_ACCESS : PROCESS_TERMINATE;
+
+      proc_hand = OpenProcess (desiredAccess, 0, pid);
       if (proc_hand == NULL)
         {
          errno = EPERM;
@@ -2651,6 +2660,43 @@ sys_kill (pid_t pid, int sig)
          rc = -1;
        }
     }
+  else if (sig == SIGTRAP)
+    {
+      static DebugBreakProcess_Proc s_pfn_Debug_Break_Process = NULL;
+
+      if (g_b_init_debug_break_process == 0)
+       {
+         g_b_init_debug_break_process = 1;
+         s_pfn_Debug_Break_Process = (DebugBreakProcess_Proc)
+           GetProcAddress (GetModuleHandle ("kernel32.dll"),
+                           "DebugBreakProcess");
+       }
+
+      if (s_pfn_Debug_Break_Process == NULL)
+       {
+         errno = ENOTSUP;
+         rc = -1;
+       }
+      else if (!s_pfn_Debug_Break_Process (proc_hand))
+       {
+         DWORD err = GetLastError ();
+
+         DebPrint (("sys_kill.DebugBreakProcess return %d "
+                    "for pid %lu\n", err, pid));
+
+         switch (err)
+           {
+           case ERROR_ACCESS_DENIED:
+             errno = EPERM;
+             break;
+           default:
+             errno = EINVAL;
+             break;
+           }
+
+         rc = -1;
+       }
+    }
   else
     {
       if (NILP (Vw32_start_process_share_console) && cp && cp->hwnd)