From: Alain Schneble Date: Sat, 8 Oct 2016 13:52:40 +0000 (+0300) Subject: Support SIGTRAP in kill emulation on Windows X-Git-Tag: emacs-26.0.90~1499 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=f3eedc7e68d0e8b97425b72d691593d06639df88;p=emacs.git Support SIGTRAP in kill emulation on Windows * 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. --- diff --git a/etc/NEWS b/etc/NEWS index 59fb72a2bec..14450a6bbe5 100644 --- 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. + ---------------------------------------------------------------------- This file is part of GNU Emacs. diff --git a/src/w32.c b/src/w32.c index f9110853799..517e286eaa9 100644 --- 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 diff --git a/src/w32proc.c b/src/w32proc.c index aef4e44d73a..189034c4e2d 100644 --- a/src/w32proc.c +++ b/src/w32proc.c @@ -69,6 +69,8 @@ along with GNU Emacs. If not, see . */ + (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)