aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2012-09-04 11:29:04 -0700
committerPaul Eggert2012-09-04 11:29:04 -0700
commitcf29dd84d205e1c78fed5d1ea0006a382658598c (patch)
tree7e6806fdd94ef53cda78db6b29a4df0276408eb4 /src
parent972debf2e7381b4fd2c70f9c1fd585d8bd137917 (diff)
downloademacs-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.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog19
-rw-r--r--src/alloc.c9
-rw-r--r--src/emacs.c14
-rw-r--r--src/lisp.h2
-rw-r--r--src/sysdep.c21
5 files changed, 55 insertions, 10 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index b2634c4fdc4..ea3b3a92e01 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,22 @@
12012-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
12012-09-04 Stefan Monnier <monnier@iro.umontreal.ca> 202012-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
6690bool suppress_checking; 6688bool suppress_checking;
6691 6689
6692void 6690void
6693die (const char *msg, const char *file, int line) 6691die (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
298fatal_error_signal (int sig) 298fatal_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
307fatal_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
3267extern void fatal_error_signal (int); 3267extern void fatal_error_signal (int);
3268#endif 3268#endif
3269extern _Noreturn void fatal_error_backtrace (int, int);
3269extern Lisp_Object Qkill_emacs; 3270extern Lisp_Object Qkill_emacs;
3270#if HAVE_SETLOCALE 3271#if HAVE_SETLOCALE
3271void fixup_locale (void); 3272void fixup_locale (void);
@@ -3412,6 +3413,7 @@ extern int set_window_size (int, int, int);
3412extern EMACS_INT get_random (void); 3413extern EMACS_INT get_random (void);
3413extern void seed_random (void *, ptrdiff_t); 3414extern void seed_random (void *, ptrdiff_t);
3414extern void init_random (void); 3415extern void init_random (void);
3416extern void emacs_backtrace (int);
3415extern _Noreturn void emacs_abort (void) NO_INLINE; 3417extern _Noreturn void emacs_abort (void) NO_INLINE;
3416extern int emacs_open (const char *, int, int); 3418extern int emacs_open (const char *, int, int);
3417extern int emacs_close (int); 3419extern 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. */
1864void
1865emacs_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. */
1861void 1880void
1862emacs_abort (void) 1881emacs_abort (void)
1863{ 1882{
1864 abort (); 1883 fatal_error_backtrace (SIGABRT, 10);
1865} 1884}
1866#endif 1885#endif
1867 1886