diff options
| author | Paul Eggert | 2012-09-04 11:29:04 -0700 |
|---|---|---|
| committer | Paul Eggert | 2012-09-04 11:29:04 -0700 |
| commit | cf29dd84d205e1c78fed5d1ea0006a382658598c (patch) | |
| tree | 7e6806fdd94ef53cda78db6b29a4df0276408eb4 | |
| parent | 972debf2e7381b4fd2c70f9c1fd585d8bd137917 (diff) | |
| download | emacs-cf29dd84d205e1c78fed5d1ea0006a382658598c.tar.gz emacs-cf29dd84d205e1c78fed5d1ea0006a382658598c.zip | |
Give more-useful info on a fatal error (Bug#12328).
* doc/emacs/trouble.texi (Crashing): New section, documenting this.
* etc/NEWS: Document the change.
* src/alloc.c [ENABLE_CHECKING]: Do not include <execinfo.h>.
(die) [ENABLE_CHECKING]: Call fatal_error_backtrace instead
of doing the work ourselves.
* src/emacs.c (fatal_error_signal): Let fatal_error_backtrace
do most of the work.
(fatal_error_backtrace): New function, taken from the guts
of the old fatal_error_signal, but with a new option to output
a backtrace.
(shut_down_emacs) [!DOS_NT]: Use strsignal to give more-useful
info about the signal than just its number.
* src/lisp.h (fatal_error_backtrace, emacs_backtrace): New decls.
* src/sysdep.c: Include <execinfo.h>
(emacs_backtrace): New function, taken partly from the previous
code of the 'die' function.
(emacs_abort): Call fatal_error_backtrace rather than abort.
| -rw-r--r-- | doc/emacs/ChangeLog | 5 | ||||
| -rw-r--r-- | doc/emacs/emacs.texi | 3 | ||||
| -rw-r--r-- | doc/emacs/trouble.texi | 39 | ||||
| -rw-r--r-- | etc/ChangeLog | 5 | ||||
| -rw-r--r-- | etc/NEWS | 5 | ||||
| -rw-r--r-- | src/ChangeLog | 19 | ||||
| -rw-r--r-- | src/alloc.c | 9 | ||||
| -rw-r--r-- | src/emacs.c | 14 | ||||
| -rw-r--r-- | src/lisp.h | 2 | ||||
| -rw-r--r-- | src/sysdep.c | 21 |
10 files changed, 111 insertions, 11 deletions
diff --git a/doc/emacs/ChangeLog b/doc/emacs/ChangeLog index a4f9985ad85..78f1d2c8e3b 100644 --- a/doc/emacs/ChangeLog +++ b/doc/emacs/ChangeLog | |||
| @@ -1,3 +1,8 @@ | |||
| 1 | 2012-09-04 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | Give more-useful info on a fatal error (Bug#12328). | ||
| 4 | * trouble.texi (Crashing): New section, documenting this. | ||
| 5 | |||
| 1 | 2012-08-24 Michael Albinus <michael.albinus@gmx.de> | 6 | 2012-08-24 Michael Albinus <michael.albinus@gmx.de> |
| 2 | 7 | ||
| 3 | * cmdargs.texi (General Variables): Setting | 8 | * cmdargs.texi (General Variables): Setting |
diff --git a/doc/emacs/emacs.texi b/doc/emacs/emacs.texi index 6357aebc6ff..192a9a2bb28 100644 --- a/doc/emacs/emacs.texi +++ b/doc/emacs/emacs.texi | |||
| @@ -1136,6 +1136,7 @@ Dealing with Emacs Trouble | |||
| 1136 | * Screen Garbled:: Garbage on the screen. | 1136 | * Screen Garbled:: Garbage on the screen. |
| 1137 | * Text Garbled:: Garbage in the text. | 1137 | * Text Garbled:: Garbage in the text. |
| 1138 | * Memory Full:: How to cope when you run out of memory. | 1138 | * Memory Full:: How to cope when you run out of memory. |
| 1139 | * Crashing:: What Emacs does when it crashes. | ||
| 1139 | * After a Crash:: Recovering editing in an Emacs session that crashed. | 1140 | * After a Crash:: Recovering editing in an Emacs session that crashed. |
| 1140 | * Emergency Escape:: What to do if Emacs stops responding. | 1141 | * Emergency Escape:: What to do if Emacs stops responding. |
| 1141 | 1142 | ||
| @@ -1320,7 +1321,7 @@ when you get it, not just free for the manufacturer. | |||
| 1320 | If you find GNU Emacs useful, please @strong{send a donation} to the | 1321 | If you find GNU Emacs useful, please @strong{send a donation} to the |
| 1321 | Free Software Foundation to support our work. Donations to the Free | 1322 | Free Software Foundation to support our work. Donations to the Free |
| 1322 | Software Foundation are tax deductible in the US. If you use GNU Emacs | 1323 | Software Foundation are tax deductible in the US. If you use GNU Emacs |
| 1323 | at your workplace, please suggest that the company make a donation. | 1324 | at your workplace, please suggest that the company make a donation. |
| 1324 | For more information on how you can help, see | 1325 | For more information on how you can help, see |
| 1325 | @url{http://www.gnu.org/help/help.html}. | 1326 | @url{http://www.gnu.org/help/help.html}. |
| 1326 | 1327 | ||
diff --git a/doc/emacs/trouble.texi b/doc/emacs/trouble.texi index 025185c583f..1806339e45d 100644 --- a/doc/emacs/trouble.texi +++ b/doc/emacs/trouble.texi | |||
| @@ -149,6 +149,7 @@ Emacs. | |||
| 149 | * Screen Garbled:: Garbage on the screen. | 149 | * Screen Garbled:: Garbage on the screen. |
| 150 | * Text Garbled:: Garbage in the text. | 150 | * Text Garbled:: Garbage in the text. |
| 151 | * Memory Full:: How to cope when you run out of memory. | 151 | * Memory Full:: How to cope when you run out of memory. |
| 152 | * Crashing:: What Emacs does when it crashes. | ||
| 152 | * After a Crash:: Recovering editing in an Emacs session that crashed. | 153 | * After a Crash:: Recovering editing in an Emacs session that crashed. |
| 153 | * Emergency Escape:: What to do if Emacs stops responding. | 154 | * Emergency Escape:: What to do if Emacs stops responding. |
| 154 | @end menu | 155 | @end menu |
| @@ -277,6 +278,44 @@ editing in the same Emacs session. | |||
| 277 | out of memory, because the buffer menu needs a fair amount of memory | 278 | out of memory, because the buffer menu needs a fair amount of memory |
| 278 | itself, and the reserve supply may not be enough. | 279 | itself, and the reserve supply may not be enough. |
| 279 | 280 | ||
| 281 | @node Crashing | ||
| 282 | @subsection When Emacs Crashes | ||
| 283 | |||
| 284 | Emacs is not supposed to crash, but if it does, before it exits it | ||
| 285 | reports some information about the crash to the standard error stream | ||
| 286 | @code{stderr}. This report may be useful to someone who later debugs | ||
| 287 | the same version of Emacs on the same platform. The format of this | ||
| 288 | report depends on the platform, and some platforms support backtraces. | ||
| 289 | Here is an example, generated on x86-64 GNU/Linux with version 2.15 of | ||
| 290 | the GNU C Library: | ||
| 291 | |||
| 292 | @example | ||
| 293 | Fatal error 11: Segmentation fault | ||
| 294 | Backtrace: | ||
| 295 | emacs[0x5094e4] | ||
| 296 | emacs[0x4ed3e6] | ||
| 297 | emacs[0x4ed504] | ||
| 298 | /lib64/libpthread.so.0[0x375220efe0] | ||
| 299 | /lib64/libpthread.so.0(read+0xe)[0x375220e08e] | ||
| 300 | emacs[0x509af6] | ||
| 301 | emacs[0x5acc26] | ||
| 302 | emacs[0x5adbfb] | ||
| 303 | emacs[0x56566b] | ||
| 304 | emacs[0x59bac3] | ||
| 305 | emacs[0x565151] | ||
| 306 | ... | ||
| 307 | @end example | ||
| 308 | |||
| 309 | @noindent | ||
| 310 | The number @samp{11} is the system signal number that corresponds to | ||
| 311 | the problem, a segmentation fault here. The hexadecimal program | ||
| 312 | addresses can be useful in debugging sessions. For example, the GDB | ||
| 313 | command @samp{list *0x509af6} prints the source-code lines | ||
| 314 | corresponding to the @samp{emacs[0x509af6]} entry in the backtrace. | ||
| 315 | |||
| 316 | The three dots at the end indicate that Emacs suppressed further | ||
| 317 | backtrace entries, in the interest of brevity. | ||
| 318 | |||
| 280 | @node After a Crash | 319 | @node After a Crash |
| 281 | @subsection Recovery After a Crash | 320 | @subsection Recovery After a Crash |
| 282 | 321 | ||
diff --git a/etc/ChangeLog b/etc/ChangeLog index f3f244c7e39..aa788275256 100644 --- a/etc/ChangeLog +++ b/etc/ChangeLog | |||
| @@ -1,3 +1,8 @@ | |||
| 1 | 2012-09-04 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | Give more-useful info on a fatal error (Bug#12328). | ||
| 4 | * NEWS: Document the change. | ||
| 5 | |||
| 1 | 2012-09-01 Paul Eggert <eggert@cs.ucla.edu> | 6 | 2012-09-01 Paul Eggert <eggert@cs.ucla.edu> |
| 2 | 7 | ||
| 3 | Better seeds for (random). | 8 | Better seeds for (random). |
| @@ -97,6 +97,11 @@ machines. Other functions that use this format, such as | |||
| 97 | file-attributes and format-time-string, have been changed accordingly. | 97 | file-attributes and format-time-string, have been changed accordingly. |
| 98 | Old-format time stamps are still accepted. | 98 | Old-format time stamps are still accepted. |
| 99 | 99 | ||
| 100 | ** Emacs now generates backtraces on fatal errors. | ||
| 101 | On encountering a fatal error, Emacs now outputs a textual description | ||
| 102 | of the fatal signal, and a short backtrace on platforms like glibc | ||
| 103 | that support backtraces. | ||
| 104 | |||
| 100 | ** New functions `system-users', `system-groups' return lists of the user | 105 | ** New functions `system-users', `system-groups' return lists of the user |
| 101 | name, group names known to the system (where possible). | 106 | name, group names known to the system (where possible). |
| 102 | 107 | ||
diff --git a/src/ChangeLog b/src/ChangeLog index b2634c4fdc4..ea3b3a92e01 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,22 @@ | |||
| 1 | 2012-09-04 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | Give more-useful info on a fatal error (Bug#12328). | ||
| 4 | * alloc.c [ENABLE_CHECKING]: Do not include <execinfo.h>. | ||
| 5 | (die) [ENABLE_CHECKING]: Call fatal_error_backtrace instead | ||
| 6 | of doing the work ourselves. | ||
| 7 | * emacs.c (fatal_error_signal): Let fatal_error_backtrace | ||
| 8 | do most of the work. | ||
| 9 | (fatal_error_backtrace): New function, taken from the guts | ||
| 10 | of the old fatal_error_signal, but with a new option to output | ||
| 11 | a backtrace. | ||
| 12 | (shut_down_emacs) [!DOS_NT]: Use strsignal to give more-useful | ||
| 13 | info about the signal than just its number. | ||
| 14 | * lisp.h (fatal_error_backtrace, emacs_backtrace): New decls. | ||
| 15 | * sysdep.c: Include <execinfo.h> | ||
| 16 | (emacs_backtrace): New function, taken partly from the previous | ||
| 17 | code of the 'die' function. | ||
| 18 | (emacs_abort): Call fatal_error_backtrace rather than abort. | ||
| 19 | |||
| 1 | 2012-09-04 Stefan Monnier <monnier@iro.umontreal.ca> | 20 | 2012-09-04 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 21 | ||
| 3 | * lread.c (readevalloop): Call internal-macroexpand-for-load to perform | 22 | * lread.c (readevalloop): Call internal-macroexpand-for-load to perform |
diff --git a/src/alloc.c b/src/alloc.c index 2a831cea62a..157d3a1d799 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -6685,21 +6685,14 @@ which_symbols (Lisp_Object obj, EMACS_INT find_max) | |||
| 6685 | 6685 | ||
| 6686 | #ifdef ENABLE_CHECKING | 6686 | #ifdef ENABLE_CHECKING |
| 6687 | 6687 | ||
| 6688 | # include <execinfo.h> | ||
| 6689 | |||
| 6690 | bool suppress_checking; | 6688 | bool suppress_checking; |
| 6691 | 6689 | ||
| 6692 | void | 6690 | void |
| 6693 | die (const char *msg, const char *file, int line) | 6691 | die (const char *msg, const char *file, int line) |
| 6694 | { | 6692 | { |
| 6695 | enum { NPOINTERS_MAX = 500 }; | ||
| 6696 | void *buffer[NPOINTERS_MAX]; | ||
| 6697 | int npointers; | ||
| 6698 | fprintf (stderr, "\r\n%s:%d: Emacs fatal error: %s\r\n", | 6693 | fprintf (stderr, "\r\n%s:%d: Emacs fatal error: %s\r\n", |
| 6699 | file, line, msg); | 6694 | file, line, msg); |
| 6700 | npointers = backtrace (buffer, NPOINTERS_MAX); | 6695 | fatal_error_backtrace (SIGABRT, INT_MAX); |
| 6701 | backtrace_symbols_fd (buffer, npointers, STDERR_FILENO); | ||
| 6702 | emacs_abort (); | ||
| 6703 | } | 6696 | } |
| 6704 | #endif | 6697 | #endif |
| 6705 | 6698 | ||
diff --git a/src/emacs.c b/src/emacs.c index b242cbf8844..18f249dc899 100644 --- a/src/emacs.c +++ b/src/emacs.c | |||
| @@ -298,6 +298,14 @@ void | |||
| 298 | fatal_error_signal (int sig) | 298 | fatal_error_signal (int sig) |
| 299 | { | 299 | { |
| 300 | SIGNAL_THREAD_CHECK (sig); | 300 | SIGNAL_THREAD_CHECK (sig); |
| 301 | fatal_error_backtrace (sig, 10); | ||
| 302 | } | ||
| 303 | |||
| 304 | /* Report a fatal error due to signal SIG, output a backtrace of at | ||
| 305 | most BACKTRACE_LIMIT lines, and exit. */ | ||
| 306 | _Noreturn void | ||
| 307 | fatal_error_backtrace (int sig, int backtrace_limit) | ||
| 308 | { | ||
| 301 | fatal_error_code = sig; | 309 | fatal_error_code = sig; |
| 302 | signal (sig, SIG_DFL); | 310 | signal (sig, SIG_DFL); |
| 303 | 311 | ||
| @@ -312,6 +320,7 @@ fatal_error_signal (int sig) | |||
| 312 | Fkill_emacs (make_number (sig)); | 320 | Fkill_emacs (make_number (sig)); |
| 313 | 321 | ||
| 314 | shut_down_emacs (sig, Qnil); | 322 | shut_down_emacs (sig, Qnil); |
| 323 | emacs_backtrace (backtrace_limit); | ||
| 315 | } | 324 | } |
| 316 | 325 | ||
| 317 | /* Signal the same code; this time it will really be fatal. | 326 | /* Signal the same code; this time it will really be fatal. |
| @@ -323,6 +332,9 @@ fatal_error_signal (int sig) | |||
| 323 | #endif | 332 | #endif |
| 324 | 333 | ||
| 325 | kill (getpid (), fatal_error_code); | 334 | kill (getpid (), fatal_error_code); |
| 335 | |||
| 336 | /* This shouldn't be executed, but it prevents a warning. */ | ||
| 337 | exit (1); | ||
| 326 | } | 338 | } |
| 327 | 339 | ||
| 328 | #ifdef SIGDANGER | 340 | #ifdef SIGDANGER |
| @@ -1992,7 +2004,7 @@ shut_down_emacs (int sig, Lisp_Object stuff) | |||
| 1992 | { | 2004 | { |
| 1993 | reset_all_sys_modes (); | 2005 | reset_all_sys_modes (); |
| 1994 | if (sig && sig != SIGTERM) | 2006 | if (sig && sig != SIGTERM) |
| 1995 | fprintf (stderr, "Fatal error (%d)", sig); | 2007 | fprintf (stderr, "Fatal error %d: %s", sig, strsignal (sig)); |
| 1996 | } | 2008 | } |
| 1997 | } | 2009 | } |
| 1998 | #else | 2010 | #else |
diff --git a/src/lisp.h b/src/lisp.h index 0835795a26d..9ee9cd74b56 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -3266,6 +3266,7 @@ extern Lisp_Object Qfile_name_handler_alist; | |||
| 3266 | #ifdef FLOAT_CATCH_SIGILL | 3266 | #ifdef FLOAT_CATCH_SIGILL |
| 3267 | extern void fatal_error_signal (int); | 3267 | extern void fatal_error_signal (int); |
| 3268 | #endif | 3268 | #endif |
| 3269 | extern _Noreturn void fatal_error_backtrace (int, int); | ||
| 3269 | extern Lisp_Object Qkill_emacs; | 3270 | extern Lisp_Object Qkill_emacs; |
| 3270 | #if HAVE_SETLOCALE | 3271 | #if HAVE_SETLOCALE |
| 3271 | void fixup_locale (void); | 3272 | void fixup_locale (void); |
| @@ -3412,6 +3413,7 @@ extern int set_window_size (int, int, int); | |||
| 3412 | extern EMACS_INT get_random (void); | 3413 | extern EMACS_INT get_random (void); |
| 3413 | extern void seed_random (void *, ptrdiff_t); | 3414 | extern void seed_random (void *, ptrdiff_t); |
| 3414 | extern void init_random (void); | 3415 | extern void init_random (void); |
| 3416 | extern void emacs_backtrace (int); | ||
| 3415 | extern _Noreturn void emacs_abort (void) NO_INLINE; | 3417 | extern _Noreturn void emacs_abort (void) NO_INLINE; |
| 3416 | extern int emacs_open (const char *, int, int); | 3418 | extern int emacs_open (const char *, int, int); |
| 3417 | extern int emacs_close (int); | 3419 | extern int emacs_close (int); |
diff --git a/src/sysdep.c b/src/sysdep.c index 78164a8f02a..1f4de194c64 100644 --- a/src/sysdep.c +++ b/src/sysdep.c | |||
| @@ -21,6 +21,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 21 | 21 | ||
| 22 | #define SYSTIME_INLINE EXTERN_INLINE | 22 | #define SYSTIME_INLINE EXTERN_INLINE |
| 23 | 23 | ||
| 24 | #include <execinfo.h> | ||
| 24 | #include <signal.h> | 25 | #include <signal.h> |
| 25 | #include <stdio.h> | 26 | #include <stdio.h> |
| 26 | #include <setjmp.h> | 27 | #include <setjmp.h> |
| @@ -1856,12 +1857,30 @@ snprintf (char *buf, size_t bufsize, char const *format, ...) | |||
| 1856 | } | 1857 | } |
| 1857 | #endif | 1858 | #endif |
| 1858 | 1859 | ||
| 1860 | /* If a backtrace is available, output the top lines of it to stderr. | ||
| 1861 | Do not output more than BACKTRACE_LIMIT or BACKTRACE_LIMIT_MAX lines. | ||
| 1862 | This function may be called from a signal handler, so it should | ||
| 1863 | not invoke async-unsafe functions like malloc. */ | ||
| 1864 | void | ||
| 1865 | emacs_backtrace (int backtrace_limit) | ||
| 1866 | { | ||
| 1867 | enum { BACKTRACE_LIMIT_MAX = 500 }; | ||
| 1868 | void *buffer[BACKTRACE_LIMIT_MAX + 1]; | ||
| 1869 | int bounded_limit = min (backtrace_limit, BACKTRACE_LIMIT_MAX); | ||
| 1870 | int npointers = backtrace (buffer, bounded_limit + 1); | ||
| 1871 | if (npointers) | ||
| 1872 | ignore_value (write (STDERR_FILENO, "\nBacktrace:\n", 12)); | ||
| 1873 | backtrace_symbols_fd (buffer, bounded_limit, STDERR_FILENO); | ||
| 1874 | if (bounded_limit < npointers) | ||
| 1875 | ignore_value (write (STDERR_FILENO, "...\n", 4)); | ||
| 1876 | } | ||
| 1877 | |||
| 1859 | #ifndef HAVE_NTGUI | 1878 | #ifndef HAVE_NTGUI |
| 1860 | /* Using emacs_abort lets GDB return from a breakpoint here. */ | 1879 | /* Using emacs_abort lets GDB return from a breakpoint here. */ |
| 1861 | void | 1880 | void |
| 1862 | emacs_abort (void) | 1881 | emacs_abort (void) |
| 1863 | { | 1882 | { |
| 1864 | abort (); | 1883 | fatal_error_backtrace (SIGABRT, 10); |
| 1865 | } | 1884 | } |
| 1866 | #endif | 1885 | #endif |
| 1867 | 1886 | ||