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.
This commit is contained in:
parent
67d14c8222
commit
f3eedc7e68
3 changed files with 61 additions and 3 deletions
10
etc/NEWS
10
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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue