From: Paul Eggert Date: Tue, 4 Sep 2012 18:29:04 +0000 (-0700) Subject: Give more-useful info on a fatal error (Bug#12328). X-Git-Tag: emacs-24.2.90~411 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=cf29dd84d205e1c78fed5d1ea0006a382658598c;p=emacs.git 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 . (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 (emacs_backtrace): New function, taken partly from the previous code of the 'die' function. (emacs_abort): Call fatal_error_backtrace rather than abort. --- 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 @@ +2012-09-04 Paul Eggert + + Give more-useful info on a fatal error (Bug#12328). + * trouble.texi (Crashing): New section, documenting this. + 2012-08-24 Michael Albinus * 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 * Screen Garbled:: Garbage on the screen. * Text Garbled:: Garbage in the text. * Memory Full:: How to cope when you run out of memory. +* Crashing:: What Emacs does when it crashes. * After a Crash:: Recovering editing in an Emacs session that crashed. * Emergency Escape:: What to do if Emacs stops responding. @@ -1320,7 +1321,7 @@ when you get it, not just free for the manufacturer. If you find GNU Emacs useful, please @strong{send a donation} to the Free Software Foundation to support our work. Donations to the Free Software Foundation are tax deductible in the US. If you use GNU Emacs -at your workplace, please suggest that the company make a donation. +at your workplace, please suggest that the company make a donation. For more information on how you can help, see @url{http://www.gnu.org/help/help.html}. 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. * Screen Garbled:: Garbage on the screen. * Text Garbled:: Garbage in the text. * Memory Full:: How to cope when you run out of memory. +* Crashing:: What Emacs does when it crashes. * After a Crash:: Recovering editing in an Emacs session that crashed. * Emergency Escape:: What to do if Emacs stops responding. @end menu @@ -277,6 +278,44 @@ editing in the same Emacs session. out of memory, because the buffer menu needs a fair amount of memory itself, and the reserve supply may not be enough. +@node Crashing +@subsection When Emacs Crashes + + Emacs is not supposed to crash, but if it does, before it exits it +reports some information about the crash to the standard error stream +@code{stderr}. This report may be useful to someone who later debugs +the same version of Emacs on the same platform. The format of this +report depends on the platform, and some platforms support backtraces. +Here is an example, generated on x86-64 GNU/Linux with version 2.15 of +the GNU C Library: + +@example +Fatal error 11: Segmentation fault +Backtrace: +emacs[0x5094e4] +emacs[0x4ed3e6] +emacs[0x4ed504] +/lib64/libpthread.so.0[0x375220efe0] +/lib64/libpthread.so.0(read+0xe)[0x375220e08e] +emacs[0x509af6] +emacs[0x5acc26] +emacs[0x5adbfb] +emacs[0x56566b] +emacs[0x59bac3] +emacs[0x565151] +... +@end example + +@noindent +The number @samp{11} is the system signal number that corresponds to +the problem, a segmentation fault here. The hexadecimal program +addresses can be useful in debugging sessions. For example, the GDB +command @samp{list *0x509af6} prints the source-code lines +corresponding to the @samp{emacs[0x509af6]} entry in the backtrace. + +The three dots at the end indicate that Emacs suppressed further +backtrace entries, in the interest of brevity. + @node After a Crash @subsection Recovery After a Crash diff --git a/etc/ChangeLog b/etc/ChangeLog index f3f244c7e39..aa788275256 100644 --- a/etc/ChangeLog +++ b/etc/ChangeLog @@ -1,3 +1,8 @@ +2012-09-04 Paul Eggert + + Give more-useful info on a fatal error (Bug#12328). + * NEWS: Document the change. + 2012-09-01 Paul Eggert Better seeds for (random). diff --git a/etc/NEWS b/etc/NEWS index e4a612f6a9e..9a38deef05c 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -97,6 +97,11 @@ machines. Other functions that use this format, such as file-attributes and format-time-string, have been changed accordingly. Old-format time stamps are still accepted. +** Emacs now generates backtraces on fatal errors. +On encountering a fatal error, Emacs now outputs a textual description +of the fatal signal, and a short backtrace on platforms like glibc +that support backtraces. + ** New functions `system-users', `system-groups' return lists of the user name, group names known to the system (where possible). diff --git a/src/ChangeLog b/src/ChangeLog index b2634c4fdc4..ea3b3a92e01 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,22 @@ +2012-09-04 Paul Eggert + + Give more-useful info on a fatal error (Bug#12328). + * alloc.c [ENABLE_CHECKING]: Do not include . + (die) [ENABLE_CHECKING]: Call fatal_error_backtrace instead + of doing the work ourselves. + * 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. + * lisp.h (fatal_error_backtrace, emacs_backtrace): New decls. + * sysdep.c: Include + (emacs_backtrace): New function, taken partly from the previous + code of the 'die' function. + (emacs_abort): Call fatal_error_backtrace rather than abort. + 2012-09-04 Stefan Monnier * 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) #ifdef ENABLE_CHECKING -# include - bool suppress_checking; void die (const char *msg, const char *file, int line) { - enum { NPOINTERS_MAX = 500 }; - void *buffer[NPOINTERS_MAX]; - int npointers; fprintf (stderr, "\r\n%s:%d: Emacs fatal error: %s\r\n", file, line, msg); - npointers = backtrace (buffer, NPOINTERS_MAX); - backtrace_symbols_fd (buffer, npointers, STDERR_FILENO); - emacs_abort (); + fatal_error_backtrace (SIGABRT, INT_MAX); } #endif 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 fatal_error_signal (int sig) { SIGNAL_THREAD_CHECK (sig); + fatal_error_backtrace (sig, 10); +} + +/* Report a fatal error due to signal SIG, output a backtrace of at + most BACKTRACE_LIMIT lines, and exit. */ +_Noreturn void +fatal_error_backtrace (int sig, int backtrace_limit) +{ fatal_error_code = sig; signal (sig, SIG_DFL); @@ -312,6 +320,7 @@ fatal_error_signal (int sig) Fkill_emacs (make_number (sig)); shut_down_emacs (sig, Qnil); + emacs_backtrace (backtrace_limit); } /* Signal the same code; this time it will really be fatal. @@ -323,6 +332,9 @@ fatal_error_signal (int sig) #endif kill (getpid (), fatal_error_code); + + /* This shouldn't be executed, but it prevents a warning. */ + exit (1); } #ifdef SIGDANGER @@ -1992,7 +2004,7 @@ shut_down_emacs (int sig, Lisp_Object stuff) { reset_all_sys_modes (); if (sig && sig != SIGTERM) - fprintf (stderr, "Fatal error (%d)", sig); + fprintf (stderr, "Fatal error %d: %s", sig, strsignal (sig)); } } #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; #ifdef FLOAT_CATCH_SIGILL extern void fatal_error_signal (int); #endif +extern _Noreturn void fatal_error_backtrace (int, int); extern Lisp_Object Qkill_emacs; #if HAVE_SETLOCALE void fixup_locale (void); @@ -3412,6 +3413,7 @@ extern int set_window_size (int, int, int); extern EMACS_INT get_random (void); extern void seed_random (void *, ptrdiff_t); extern void init_random (void); +extern void emacs_backtrace (int); extern _Noreturn void emacs_abort (void) NO_INLINE; extern int emacs_open (const char *, int, int); 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 . */ #define SYSTIME_INLINE EXTERN_INLINE +#include #include #include #include @@ -1856,12 +1857,30 @@ snprintf (char *buf, size_t bufsize, char const *format, ...) } #endif +/* If a backtrace is available, output the top lines of it to stderr. + Do not output more than BACKTRACE_LIMIT or BACKTRACE_LIMIT_MAX lines. + This function may be called from a signal handler, so it should + not invoke async-unsafe functions like malloc. */ +void +emacs_backtrace (int backtrace_limit) +{ + enum { BACKTRACE_LIMIT_MAX = 500 }; + void *buffer[BACKTRACE_LIMIT_MAX + 1]; + int bounded_limit = min (backtrace_limit, BACKTRACE_LIMIT_MAX); + int npointers = backtrace (buffer, bounded_limit + 1); + if (npointers) + ignore_value (write (STDERR_FILENO, "\nBacktrace:\n", 12)); + backtrace_symbols_fd (buffer, bounded_limit, STDERR_FILENO); + if (bounded_limit < npointers) + ignore_value (write (STDERR_FILENO, "...\n", 4)); +} + #ifndef HAVE_NTGUI /* Using emacs_abort lets GDB return from a breakpoint here. */ void emacs_abort (void) { - abort (); + fatal_error_backtrace (SIGABRT, 10); } #endif