diff options
| author | Eli Zaretskii | 2012-11-02 16:00:45 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2012-11-02 16:00:45 +0200 |
| commit | 1005b4b98a43c4aea2ac8f01a5743b6b38bdd964 (patch) | |
| tree | 15933dd02566ab8cad6fd4e299612b41bbe188e0 /src | |
| parent | b9e9df47f2886bb4b6b67aea8eeb0b015258a063 (diff) | |
| download | emacs-1005b4b98a43c4aea2ac8f01a5743b6b38bdd964.tar.gz emacs-1005b4b98a43c4aea2ac8f01a5743b6b38bdd964.zip | |
Implement backtrace output for fatal errors on MS-Windows.
src/w32fns.c (CaptureStackBackTrace_proc): New typedef.
(BACKTRACE_LIMIT_MAX): New macro.
(w32_backtrace): New function.
(emacs_abort): Use w32_backtrace when the user chooses not to
attach a debugger. Update the text of the abort dialog.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 9 | ||||
| -rw-r--r-- | src/w32fns.c | 79 |
2 files changed, 85 insertions, 3 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 25cb1e76fa5..5739b5d9125 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,12 @@ | |||
| 1 | 2012-11-02 Eli Zaretskii <eliz@gnu.org> | ||
| 2 | |||
| 3 | Implement backtrace output for fatal errors on MS-Windows. | ||
| 4 | * w32fns.c (CaptureStackBackTrace_proc): New typedef. | ||
| 5 | (BACKTRACE_LIMIT_MAX): New macro. | ||
| 6 | (w32_backtrace): New function. | ||
| 7 | (emacs_abort): Use w32_backtrace when the user chooses not to | ||
| 8 | attach a debugger. Update the text of the abort dialog. | ||
| 9 | |||
| 1 | 2012-11-02 Dmitry Antipov <dmantipov@yandex.ru> | 10 | 2012-11-02 Dmitry Antipov <dmantipov@yandex.ru> |
| 2 | 11 | ||
| 3 | Window-related stuff cleanup here and there. | 12 | Window-related stuff cleanup here and there. |
diff --git a/src/w32fns.c b/src/w32fns.c index aa120d59ce5..7459c4a31db 100644 --- a/src/w32fns.c +++ b/src/w32fns.c | |||
| @@ -26,6 +26,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 26 | #include <limits.h> | 26 | #include <limits.h> |
| 27 | #include <errno.h> | 27 | #include <errno.h> |
| 28 | #include <math.h> | 28 | #include <math.h> |
| 29 | #include <fcntl.h> | ||
| 29 | 30 | ||
| 30 | #include "lisp.h" | 31 | #include "lisp.h" |
| 31 | #include "w32term.h" | 32 | #include "w32term.h" |
| @@ -7697,6 +7698,30 @@ globals_of_w32fns (void) | |||
| 7697 | syms_of_w32uniscribe (); | 7698 | syms_of_w32uniscribe (); |
| 7698 | } | 7699 | } |
| 7699 | 7700 | ||
| 7701 | typedef USHORT (WINAPI * CaptureStackBackTrace_proc) (ULONG, ULONG, PVOID *, | ||
| 7702 | PULONG); | ||
| 7703 | |||
| 7704 | #define BACKTRACE_LIMIT_MAX 62 | ||
| 7705 | |||
| 7706 | int | ||
| 7707 | w32_backtrace (void **buffer, int limit) | ||
| 7708 | { | ||
| 7709 | static CaptureStackBackTrace_proc s_pfn_CaptureStackBackTrace = NULL; | ||
| 7710 | HMODULE hm_kernel32 = NULL; | ||
| 7711 | |||
| 7712 | if (!s_pfn_CaptureStackBackTrace) | ||
| 7713 | { | ||
| 7714 | hm_kernel32 = LoadLibrary ("Kernel32.dll"); | ||
| 7715 | s_pfn_CaptureStackBackTrace = | ||
| 7716 | (CaptureStackBackTrace_proc) GetProcAddress (hm_kernel32, | ||
| 7717 | "RtlCaptureStackBackTrace"); | ||
| 7718 | } | ||
| 7719 | if (s_pfn_CaptureStackBackTrace) | ||
| 7720 | return s_pfn_CaptureStackBackTrace (0, min (BACKTRACE_LIMIT_MAX, limit), | ||
| 7721 | buffer, NULL); | ||
| 7722 | return 0; | ||
| 7723 | } | ||
| 7724 | |||
| 7700 | void | 7725 | void |
| 7701 | emacs_abort (void) | 7726 | emacs_abort (void) |
| 7702 | { | 7727 | { |
| @@ -7704,7 +7729,10 @@ emacs_abort (void) | |||
| 7704 | button = MessageBox (NULL, | 7729 | button = MessageBox (NULL, |
| 7705 | "A fatal error has occurred!\n\n" | 7730 | "A fatal error has occurred!\n\n" |
| 7706 | "Would you like to attach a debugger?\n\n" | 7731 | "Would you like to attach a debugger?\n\n" |
| 7707 | "Select YES to debug, NO to abort Emacs" | 7732 | "Select:\n" |
| 7733 | "YES -- to debug Emacs, or\n" | ||
| 7734 | "NO -- to abort Emacs and produce a backtrace\n" | ||
| 7735 | " (emacs_backtrace.txt in current directory)." | ||
| 7708 | #if __GNUC__ | 7736 | #if __GNUC__ |
| 7709 | "\n\n(type \"gdb -p <emacs-PID>\" and\n" | 7737 | "\n\n(type \"gdb -p <emacs-PID>\" and\n" |
| 7710 | "\"continue\" inside GDB before clicking YES.)" | 7738 | "\"continue\" inside GDB before clicking YES.)" |
| @@ -7719,7 +7747,52 @@ emacs_abort (void) | |||
| 7719 | exit (2); /* tell the compiler we will never return */ | 7747 | exit (2); /* tell the compiler we will never return */ |
| 7720 | case IDNO: | 7748 | case IDNO: |
| 7721 | default: | 7749 | default: |
| 7722 | abort (); | 7750 | { |
| 7723 | break; | 7751 | void *stack[BACKTRACE_LIMIT_MAX + 1]; |
| 7752 | int i = w32_backtrace (stack, BACKTRACE_LIMIT_MAX + 1); | ||
| 7753 | |||
| 7754 | if (i) | ||
| 7755 | { | ||
| 7756 | HANDLE errout = GetStdHandle (STD_ERROR_HANDLE); | ||
| 7757 | int stderr_fd = -1, errfile_fd = -1; | ||
| 7758 | int j; | ||
| 7759 | |||
| 7760 | if (errout && errout != INVALID_HANDLE_VALUE) | ||
| 7761 | stderr_fd = _open_osfhandle ((intptr_t)errout, O_APPEND | O_BINARY); | ||
| 7762 | if (stderr_fd >= 0) | ||
| 7763 | write (stderr_fd, "\r\nBacktrace:\r\n", 14); | ||
| 7764 | errfile_fd = _open ("emacs_backtrace.txt", O_RDWR | O_CREAT | O_BINARY, S_IREAD | S_IWRITE); | ||
| 7765 | if (errfile_fd >= 0) | ||
| 7766 | { | ||
| 7767 | lseek (errfile_fd, 0L, SEEK_END); | ||
| 7768 | write (errfile_fd, "\r\nBacktrace:\r\n", 14); | ||
| 7769 | } | ||
| 7770 | |||
| 7771 | for (j = 0; j < i; j++) | ||
| 7772 | { | ||
| 7773 | char buf[INT_BUFSIZE_BOUND (void *)]; | ||
| 7774 | |||
| 7775 | /* stack[] gives the return addresses, whereas we want | ||
| 7776 | the address of the call, so decrease each address | ||
| 7777 | by approximate size of 1 CALL instruction. */ | ||
| 7778 | sprintf (buf, "0x%p\r\n", stack[j] - sizeof(void *)); | ||
| 7779 | if (stderr_fd >= 0) | ||
| 7780 | write (stderr_fd, buf, strlen (buf)); | ||
| 7781 | if (errfile_fd >= 0) | ||
| 7782 | write (errfile_fd, buf, strlen (buf)); | ||
| 7783 | } | ||
| 7784 | if (i == BACKTRACE_LIMIT_MAX) | ||
| 7785 | { | ||
| 7786 | if (stderr_fd >= 0) | ||
| 7787 | write (stderr_fd, "...\r\n", 5); | ||
| 7788 | if (errfile_fd >= 0) | ||
| 7789 | write (errfile_fd, "...\r\n", 5); | ||
| 7790 | } | ||
| 7791 | if (errfile_fd >= 0) | ||
| 7792 | close (errfile_fd); | ||
| 7793 | } | ||
| 7794 | abort (); | ||
| 7795 | break; | ||
| 7796 | } | ||
| 7724 | } | 7797 | } |
| 7725 | } | 7798 | } |