aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog11
-rw-r--r--src/w32fns.c169
2 files changed, 121 insertions, 59 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index db311bdcba5..a5c6668c551 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,14 @@
12013-12-02 Eli Zaretskii <eliz@gnu.org>
2
3 Improve reporting of fatal exception on MS-Windows.
4 * w32fns.c (my_exception_handler): New function.
5 (globals_of_w32fns): Set it up as the unhandled exception
6 handler. Initialize exception code and address to zeros.
7 (emacs_abort): If the exception code and address are available,
8 print them at the beginning of the backtrace. Fix the format of
9 printing addresses (was producing 0x0x12345678 on XP).
10 (Bug#15994)
11
12013-12-02 Helmut Eller <eller.helmut@gmail.com> 122013-12-02 Helmut Eller <eller.helmut@gmail.com>
2 13
3 * eval.c (Fbacktrace__locals): New function. 14 * eval.c (Fbacktrace__locals): New function.
diff --git a/src/w32fns.c b/src/w32fns.c
index f574a86b1e1..79011f9afc2 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -7969,61 +7969,35 @@ only be necessary if the default setting causes problems. */);
7969#endif 7969#endif
7970} 7970}
7971 7971
7972
7972 7973
7973/* 7974/* Crashing and reporting backtrace. */
7974 globals_of_w32fns is used to initialize those global variables that
7975 must always be initialized on startup even when the global variable
7976 initialized is non zero (see the function main in emacs.c).
7977 globals_of_w32fns is called from syms_of_w32fns when the global
7978 variable initialized is 0 and directly from main when initialized
7979 is non zero.
7980 */
7981void
7982globals_of_w32fns (void)
7983{
7984 HMODULE user32_lib = GetModuleHandle ("user32.dll");
7985 /*
7986 TrackMouseEvent not available in all versions of Windows, so must load
7987 it dynamically. Do it once, here, instead of every time it is used.
7988 */
7989 track_mouse_event_fn = (TrackMouseEvent_Proc)
7990 GetProcAddress (user32_lib, "TrackMouseEvent");
7991
7992 monitor_from_point_fn = (MonitorFromPoint_Proc)
7993 GetProcAddress (user32_lib, "MonitorFromPoint");
7994 get_monitor_info_fn = (GetMonitorInfo_Proc)
7995 GetProcAddress (user32_lib, "GetMonitorInfoA");
7996 monitor_from_window_fn = (MonitorFromWindow_Proc)
7997 GetProcAddress (user32_lib, "MonitorFromWindow");
7998 enum_display_monitors_fn = (EnumDisplayMonitors_Proc)
7999 GetProcAddress (user32_lib, "EnumDisplayMonitors");
8000
8001 {
8002 HMODULE imm32_lib = GetModuleHandle ("imm32.dll");
8003 get_composition_string_fn = (ImmGetCompositionString_Proc)
8004 GetProcAddress (imm32_lib, "ImmGetCompositionStringW");
8005 get_ime_context_fn = (ImmGetContext_Proc)
8006 GetProcAddress (imm32_lib, "ImmGetContext");
8007 release_ime_context_fn = (ImmReleaseContext_Proc)
8008 GetProcAddress (imm32_lib, "ImmReleaseContext");
8009 set_ime_composition_window_fn = (ImmSetCompositionWindow_Proc)
8010 GetProcAddress (imm32_lib, "ImmSetCompositionWindow");
8011 }
8012 DEFVAR_INT ("w32-ansi-code-page",
8013 w32_ansi_code_page,
8014 doc: /* The ANSI code page used by the system. */);
8015 w32_ansi_code_page = GetACP ();
8016
8017 if (os_subtype == OS_NT)
8018 w32_unicode_gui = 1;
8019 else
8020 w32_unicode_gui = 0;
8021 7975
8022 /* MessageBox does not work without this when linked to comctl32.dll 6.0. */ 7976#ifndef CYGWIN
8023 InitCommonControls (); 7977static LONG CALLBACK my_exception_handler (EXCEPTION_POINTERS *);
7978static LPTOP_LEVEL_EXCEPTION_FILTER prev_exception_handler;
7979#endif
7980static DWORD except_code;
7981static PVOID except_addr;
8024 7982
8025 syms_of_w32uniscribe (); 7983#ifndef CYGWIN
7984/* This handler records the exception code and the address where it
7985 was triggered so that this info could be included in the backtrace.
7986 Without that, the backtrace in some cases has no information
7987 whatsoever about the offending code, and looks as if the top-level
7988 exception handler in the MinGW startup code di the one that
7989 crashed. */
7990static LONG CALLBACK
7991my_exception_handler (EXCEPTION_POINTERS * exception_data)
7992{
7993 except_code = exception_data->ExceptionRecord->ExceptionCode;
7994 except_addr = exception_data->ExceptionRecord->ExceptionAddress;
7995
7996 if (prev_exception_handler)
7997 return prev_exception_handler (exception_data);
7998 return EXCEPTION_EXECUTE_HANDLER;
8026} 7999}
8000#endif
8027 8001
8028typedef USHORT (WINAPI * CaptureStackBackTrace_proc) (ULONG, ULONG, PVOID *, 8002typedef USHORT (WINAPI * CaptureStackBackTrace_proc) (ULONG, ULONG, PVOID *,
8029 PULONG); 8003 PULONG);
@@ -8080,21 +8054,32 @@ emacs_abort (void)
8080 8054
8081 if (i) 8055 if (i)
8082 { 8056 {
8057 int errfile_fd = -1;
8058 int j;
8059 char buf[sizeof ("\r\nException at this address:\r\n\r\n")
8060 + 2 * INT_BUFSIZE_BOUND (void *)];
8083#ifdef CYGWIN 8061#ifdef CYGWIN
8084 int stderr_fd = 2; 8062 int stderr_fd = 2;
8085#else 8063#else
8086 HANDLE errout = GetStdHandle (STD_ERROR_HANDLE); 8064 HANDLE errout = GetStdHandle (STD_ERROR_HANDLE);
8087 int stderr_fd = -1; 8065 int stderr_fd = -1;
8088#endif
8089 int errfile_fd = -1;
8090 int j;
8091 8066
8092#ifndef CYGWIN
8093 if (errout && errout != INVALID_HANDLE_VALUE) 8067 if (errout && errout != INVALID_HANDLE_VALUE)
8094 stderr_fd = _open_osfhandle ((intptr_t)errout, O_APPEND | O_BINARY); 8068 stderr_fd = _open_osfhandle ((intptr_t)errout, O_APPEND | O_BINARY);
8095#endif 8069#endif
8070
8071 /* We use %p, not 0x%p, as %p produces a leading "0x" on XP,
8072 but not on Windows 7. addr2line doesn't mind a missing
8073 "0x", but will be confused by an extra one. */
8074 if (except_addr)
8075 sprintf (buf, "\r\nException 0x%lx at this address:\r\n%p\r\n",
8076 except_code, except_addr);
8096 if (stderr_fd >= 0) 8077 if (stderr_fd >= 0)
8097 write (stderr_fd, "\r\nBacktrace:\r\n", 14); 8078 {
8079 if (except_addr)
8080 write (stderr_fd, buf, strlen (buf));
8081 write (stderr_fd, "\r\nBacktrace:\r\n", 14);
8082 }
8098#ifdef CYGWIN 8083#ifdef CYGWIN
8099#define _open open 8084#define _open open
8100#endif 8085#endif
@@ -8102,17 +8087,17 @@ emacs_abort (void)
8102 if (errfile_fd >= 0) 8087 if (errfile_fd >= 0)
8103 { 8088 {
8104 lseek (errfile_fd, 0L, SEEK_END); 8089 lseek (errfile_fd, 0L, SEEK_END);
8090 if (except_addr)
8091 write (errfile_fd, buf, strlen (buf));
8105 write (errfile_fd, "\r\nBacktrace:\r\n", 14); 8092 write (errfile_fd, "\r\nBacktrace:\r\n", 14);
8106 } 8093 }
8107 8094
8108 for (j = 0; j < i; j++) 8095 for (j = 0; j < i; j++)
8109 { 8096 {
8110 char buf[INT_BUFSIZE_BOUND (void *)];
8111
8112 /* stack[] gives the return addresses, whereas we want 8097 /* stack[] gives the return addresses, whereas we want
8113 the address of the call, so decrease each address 8098 the address of the call, so decrease each address
8114 by approximate size of 1 CALL instruction. */ 8099 by approximate size of 1 CALL instruction. */
8115 sprintf (buf, "0x%p\r\n", (char *)stack[j] - sizeof(void *)); 8100 sprintf (buf, "%p\r\n", (char *)stack[j] - sizeof(void *));
8116 if (stderr_fd >= 0) 8101 if (stderr_fd >= 0)
8117 write (stderr_fd, buf, strlen (buf)); 8102 write (stderr_fd, buf, strlen (buf));
8118 if (errfile_fd >= 0) 8103 if (errfile_fd >= 0)
@@ -8134,6 +8119,72 @@ emacs_abort (void)
8134 } 8119 }
8135} 8120}
8136 8121
8122
8123
8124/* Initialization. */
8125
8126/*
8127 globals_of_w32fns is used to initialize those global variables that
8128 must always be initialized on startup even when the global variable
8129 initialized is non zero (see the function main in emacs.c).
8130 globals_of_w32fns is called from syms_of_w32fns when the global
8131 variable initialized is 0 and directly from main when initialized
8132 is non zero.
8133 */
8134void
8135globals_of_w32fns (void)
8136{
8137 HMODULE user32_lib = GetModuleHandle ("user32.dll");
8138 /*
8139 TrackMouseEvent not available in all versions of Windows, so must load
8140 it dynamically. Do it once, here, instead of every time it is used.
8141 */
8142 track_mouse_event_fn = (TrackMouseEvent_Proc)
8143 GetProcAddress (user32_lib, "TrackMouseEvent");
8144
8145 monitor_from_point_fn = (MonitorFromPoint_Proc)
8146 GetProcAddress (user32_lib, "MonitorFromPoint");
8147 get_monitor_info_fn = (GetMonitorInfo_Proc)
8148 GetProcAddress (user32_lib, "GetMonitorInfoA");
8149 monitor_from_window_fn = (MonitorFromWindow_Proc)
8150 GetProcAddress (user32_lib, "MonitorFromWindow");
8151 enum_display_monitors_fn = (EnumDisplayMonitors_Proc)
8152 GetProcAddress (user32_lib, "EnumDisplayMonitors");
8153
8154 {
8155 HMODULE imm32_lib = GetModuleHandle ("imm32.dll");
8156 get_composition_string_fn = (ImmGetCompositionString_Proc)
8157 GetProcAddress (imm32_lib, "ImmGetCompositionStringW");
8158 get_ime_context_fn = (ImmGetContext_Proc)
8159 GetProcAddress (imm32_lib, "ImmGetContext");
8160 release_ime_context_fn = (ImmReleaseContext_Proc)
8161 GetProcAddress (imm32_lib, "ImmReleaseContext");
8162 set_ime_composition_window_fn = (ImmSetCompositionWindow_Proc)
8163 GetProcAddress (imm32_lib, "ImmSetCompositionWindow");
8164 }
8165
8166 except_code = 0;
8167 except_addr = 0;
8168#ifndef CYGWIN
8169 prev_exception_handler = SetUnhandledExceptionFilter (my_exception_handler);
8170#endif
8171
8172 DEFVAR_INT ("w32-ansi-code-page",
8173 w32_ansi_code_page,
8174 doc: /* The ANSI code page used by the system. */);
8175 w32_ansi_code_page = GetACP ();
8176
8177 if (os_subtype == OS_NT)
8178 w32_unicode_gui = 1;
8179 else
8180 w32_unicode_gui = 0;
8181
8182 /* MessageBox does not work without this when linked to comctl32.dll 6.0. */
8183 InitCommonControls ();
8184
8185 syms_of_w32uniscribe ();
8186}
8187
8137#ifdef NTGUI_UNICODE 8188#ifdef NTGUI_UNICODE
8138 8189
8139Lisp_Object 8190Lisp_Object