[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] trunk r115351: Improve reporting of fatal exception on MS-
From: |
Eli Zaretskii |
Subject: |
[Emacs-diffs] trunk r115351: Improve reporting of fatal exception on MS-Windows, to aid debugging #15994. |
Date: |
Mon, 02 Dec 2013 17:29:06 +0000 |
User-agent: |
Bazaar (2.6b2) |
------------------------------------------------------------
revno: 115351
revision-id: address@hidden
parent: address@hidden
fixes bug: http://debbugs.gnu.org/15994
committer: Eli Zaretskii <address@hidden>
branch nick: trunk
timestamp: Mon 2013-12-02 19:28:17 +0200
message:
Improve reporting of fatal exception on MS-Windows, to aid debugging #15994.
src/w32fns.c (my_exception_handler): New function.
(globals_of_w32fns): Set it up as the unhandled exception
handler. Initialize exception code and address to zeros.
(emacs_abort): If the exception code and address are available,
print them at the beginning of the backtrace. Fix the format of
printing addresses (was producing 0x0x12345678 on XP).
modified:
src/ChangeLog changelog-20091113204419-o5vbwnq5f7feedwu-1438
src/w32fns.c w32fns.c-20091113204419-o5vbwnq5f7feedwu-945
=== modified file 'src/ChangeLog'
--- a/src/ChangeLog 2013-12-02 14:45:22 +0000
+++ b/src/ChangeLog 2013-12-02 17:28:17 +0000
@@ -1,3 +1,14 @@
+2013-12-02 Eli Zaretskii <address@hidden>
+
+ Improve reporting of fatal exception on MS-Windows.
+ * w32fns.c (my_exception_handler): New function.
+ (globals_of_w32fns): Set it up as the unhandled exception
+ handler. Initialize exception code and address to zeros.
+ (emacs_abort): If the exception code and address are available,
+ print them at the beginning of the backtrace. Fix the format of
+ printing addresses (was producing 0x0x12345678 on XP).
+ (Bug#15994)
+
2013-12-02 Helmut Eller <address@hidden>
* eval.c (Fbacktrace__locals): New function.
=== modified file 'src/w32fns.c'
--- a/src/w32fns.c 2013-12-01 22:33:13 +0000
+++ b/src/w32fns.c 2013-12-02 17:28:17 +0000
@@ -7969,61 +7969,35 @@
#endif
}
-
-/*
- globals_of_w32fns is used to initialize those global variables that
- must always be initialized on startup even when the global variable
- initialized is non zero (see the function main in emacs.c).
- globals_of_w32fns is called from syms_of_w32fns when the global
- variable initialized is 0 and directly from main when initialized
- is non zero.
- */
-void
-globals_of_w32fns (void)
+
+
+/* Crashing and reporting backtrace. */
+
+#ifndef CYGWIN
+static LONG CALLBACK my_exception_handler (EXCEPTION_POINTERS *);
+static LPTOP_LEVEL_EXCEPTION_FILTER prev_exception_handler;
+#endif
+static DWORD except_code;
+static PVOID except_addr;
+
+#ifndef CYGWIN
+/* This handler records the exception code and the address where it
+ was triggered so that this info could be included in the backtrace.
+ Without that, the backtrace in some cases has no information
+ whatsoever about the offending code, and looks as if the top-level
+ exception handler in the MinGW startup code di the one that
+ crashed. */
+static LONG CALLBACK
+my_exception_handler (EXCEPTION_POINTERS * exception_data)
{
- HMODULE user32_lib = GetModuleHandle ("user32.dll");
- /*
- TrackMouseEvent not available in all versions of Windows, so must load
- it dynamically. Do it once, here, instead of every time it is used.
- */
- track_mouse_event_fn = (TrackMouseEvent_Proc)
- GetProcAddress (user32_lib, "TrackMouseEvent");
-
- monitor_from_point_fn = (MonitorFromPoint_Proc)
- GetProcAddress (user32_lib, "MonitorFromPoint");
- get_monitor_info_fn = (GetMonitorInfo_Proc)
- GetProcAddress (user32_lib, "GetMonitorInfoA");
- monitor_from_window_fn = (MonitorFromWindow_Proc)
- GetProcAddress (user32_lib, "MonitorFromWindow");
- enum_display_monitors_fn = (EnumDisplayMonitors_Proc)
- GetProcAddress (user32_lib, "EnumDisplayMonitors");
-
- {
- HMODULE imm32_lib = GetModuleHandle ("imm32.dll");
- get_composition_string_fn = (ImmGetCompositionString_Proc)
- GetProcAddress (imm32_lib, "ImmGetCompositionStringW");
- get_ime_context_fn = (ImmGetContext_Proc)
- GetProcAddress (imm32_lib, "ImmGetContext");
- release_ime_context_fn = (ImmReleaseContext_Proc)
- GetProcAddress (imm32_lib, "ImmReleaseContext");
- set_ime_composition_window_fn = (ImmSetCompositionWindow_Proc)
- GetProcAddress (imm32_lib, "ImmSetCompositionWindow");
- }
- DEFVAR_INT ("w32-ansi-code-page",
- w32_ansi_code_page,
- doc: /* The ANSI code page used by the system. */);
- w32_ansi_code_page = GetACP ();
-
- if (os_subtype == OS_NT)
- w32_unicode_gui = 1;
- else
- w32_unicode_gui = 0;
-
- /* MessageBox does not work without this when linked to comctl32.dll 6.0. */
- InitCommonControls ();
-
- syms_of_w32uniscribe ();
+ except_code = exception_data->ExceptionRecord->ExceptionCode;
+ except_addr = exception_data->ExceptionRecord->ExceptionAddress;
+
+ if (prev_exception_handler)
+ return prev_exception_handler (exception_data);
+ return EXCEPTION_EXECUTE_HANDLER;
}
+#endif
typedef USHORT (WINAPI * CaptureStackBackTrace_proc) (ULONG, ULONG, PVOID *,
PULONG);
@@ -8080,21 +8054,32 @@
if (i)
{
+ int errfile_fd = -1;
+ int j;
+ char buf[sizeof ("\r\nException at this address:\r\n\r\n")
+ + 2 * INT_BUFSIZE_BOUND (void *)];
#ifdef CYGWIN
int stderr_fd = 2;
#else
HANDLE errout = GetStdHandle (STD_ERROR_HANDLE);
int stderr_fd = -1;
-#endif
- int errfile_fd = -1;
- int j;
-#ifndef CYGWIN
if (errout && errout != INVALID_HANDLE_VALUE)
stderr_fd = _open_osfhandle ((intptr_t)errout, O_APPEND |
O_BINARY);
#endif
+
+ /* We use %p, not 0x%p, as %p produces a leading "0x" on XP,
+ but not on Windows 7. addr2line doesn't mind a missing
+ "0x", but will be confused by an extra one. */
+ if (except_addr)
+ sprintf (buf, "\r\nException 0x%lx at this address:\r\n%p\r\n",
+ except_code, except_addr);
if (stderr_fd >= 0)
- write (stderr_fd, "\r\nBacktrace:\r\n", 14);
+ {
+ if (except_addr)
+ write (stderr_fd, buf, strlen (buf));
+ write (stderr_fd, "\r\nBacktrace:\r\n", 14);
+ }
#ifdef CYGWIN
#define _open open
#endif
@@ -8102,17 +8087,17 @@
if (errfile_fd >= 0)
{
lseek (errfile_fd, 0L, SEEK_END);
+ if (except_addr)
+ write (errfile_fd, buf, strlen (buf));
write (errfile_fd, "\r\nBacktrace:\r\n", 14);
}
for (j = 0; j < i; j++)
{
- char buf[INT_BUFSIZE_BOUND (void *)];
-
/* stack[] gives the return addresses, whereas we want
the address of the call, so decrease each address
by approximate size of 1 CALL instruction. */
- sprintf (buf, "0x%p\r\n", (char *)stack[j] - sizeof(void *));
+ sprintf (buf, "%p\r\n", (char *)stack[j] - sizeof(void *));
if (stderr_fd >= 0)
write (stderr_fd, buf, strlen (buf));
if (errfile_fd >= 0)
@@ -8134,6 +8119,72 @@
}
}
+
+
+/* Initialization. */
+
+/*
+ globals_of_w32fns is used to initialize those global variables that
+ must always be initialized on startup even when the global variable
+ initialized is non zero (see the function main in emacs.c).
+ globals_of_w32fns is called from syms_of_w32fns when the global
+ variable initialized is 0 and directly from main when initialized
+ is non zero.
+ */
+void
+globals_of_w32fns (void)
+{
+ HMODULE user32_lib = GetModuleHandle ("user32.dll");
+ /*
+ TrackMouseEvent not available in all versions of Windows, so must load
+ it dynamically. Do it once, here, instead of every time it is used.
+ */
+ track_mouse_event_fn = (TrackMouseEvent_Proc)
+ GetProcAddress (user32_lib, "TrackMouseEvent");
+
+ monitor_from_point_fn = (MonitorFromPoint_Proc)
+ GetProcAddress (user32_lib, "MonitorFromPoint");
+ get_monitor_info_fn = (GetMonitorInfo_Proc)
+ GetProcAddress (user32_lib, "GetMonitorInfoA");
+ monitor_from_window_fn = (MonitorFromWindow_Proc)
+ GetProcAddress (user32_lib, "MonitorFromWindow");
+ enum_display_monitors_fn = (EnumDisplayMonitors_Proc)
+ GetProcAddress (user32_lib, "EnumDisplayMonitors");
+
+ {
+ HMODULE imm32_lib = GetModuleHandle ("imm32.dll");
+ get_composition_string_fn = (ImmGetCompositionString_Proc)
+ GetProcAddress (imm32_lib, "ImmGetCompositionStringW");
+ get_ime_context_fn = (ImmGetContext_Proc)
+ GetProcAddress (imm32_lib, "ImmGetContext");
+ release_ime_context_fn = (ImmReleaseContext_Proc)
+ GetProcAddress (imm32_lib, "ImmReleaseContext");
+ set_ime_composition_window_fn = (ImmSetCompositionWindow_Proc)
+ GetProcAddress (imm32_lib, "ImmSetCompositionWindow");
+ }
+
+ except_code = 0;
+ except_addr = 0;
+#ifndef CYGWIN
+ prev_exception_handler = SetUnhandledExceptionFilter (my_exception_handler);
+#endif
+
+ DEFVAR_INT ("w32-ansi-code-page",
+ w32_ansi_code_page,
+ doc: /* The ANSI code page used by the system. */);
+ w32_ansi_code_page = GetACP ();
+
+ if (os_subtype == OS_NT)
+ w32_unicode_gui = 1;
+ else
+ w32_unicode_gui = 0;
+
+ /* MessageBox does not work without this when linked to comctl32.dll 6.0. */
+ InitCommonControls ();
+
+ syms_of_w32uniscribe ();
+}
+
#ifdef NTGUI_UNICODE
Lisp_Object
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Emacs-diffs] trunk r115351: Improve reporting of fatal exception on MS-Windows, to aid debugging #15994.,
Eli Zaretskii <=