diff options
Diffstat (limited to 'src/emacs.c')
-rw-r--r-- | src/emacs.c | 235 |
1 files changed, 110 insertions, 125 deletions
diff --git a/src/emacs.c b/src/emacs.c index 7b643f5226f..80d536a5c14 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -20,13 +20,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <config.h> -#include <signal.h> #include <errno.h> #include <stdio.h> #include <sys/types.h> #include <sys/file.h> -#include <setjmp.h> #include <unistd.h> #include "lisp.h" @@ -101,15 +99,15 @@ extern void moncontrol (int mode); #endif static const char emacs_version[] = VERSION; -static const char emacs_copyright[] = "Copyright (C) 2012 Free Software Foundation, Inc."; +static const char emacs_copyright[] = COPYRIGHT; /* Empty lisp strings. To avoid having to build any others. */ Lisp_Object empty_unibyte_string, empty_multibyte_string; -/* Set nonzero after Emacs has started up the first time. - Prevents reinitialization of the Lisp world and keymaps - on subsequent starts. */ -int initialized; +/* Set after Emacs has started up the first time. + Prevents reinitialization of the Lisp world and keymaps + on subsequent starts. */ +bool initialized; #ifdef DARWIN_OS extern void unexec_init_emacs_zone (void); @@ -123,9 +121,9 @@ static void *malloc_state_ptr; extern void *malloc_get_state (void); /* From glibc, a routine that overwrites the malloc internal state. */ extern int malloc_set_state (void*); -/* Non-zero if the MALLOC_CHECK_ environment variable was set while +/* True if the MALLOC_CHECK_ environment variable was set while dumping. Used to work around a bug in glibc's malloc. */ -static int malloc_using_checking; +static bool malloc_using_checking; #endif Lisp_Object Qfile_name_handler_alist; @@ -134,17 +132,17 @@ Lisp_Object Qrisky_local_variable; Lisp_Object Qkill_emacs; -/* If non-zero, Emacs should not attempt to use a window-specific code, +/* If true, Emacs should not attempt to use a window-specific code, but instead should use the virtual terminal under which it was started. */ -int inhibit_window_system; +bool inhibit_window_system; -/* If non-zero, a filter or a sentinel is running. Tested to save the match +/* If true, a filter or a sentinel is running. Tested to save the match data on the first attempt to change it inside asynchronous code. */ -int running_asynch_code; +bool running_asynch_code; #if defined (HAVE_X_WINDOWS) || defined (HAVE_NS) -/* If non-zero, -d was specified, meaning we're using some window system. */ -int display_arg; +/* If true, -d was specified, meaning we're using some window system. */ +bool display_arg; #endif /* An address near the bottom of the stack. @@ -177,11 +175,11 @@ static uprintmax_t heap_bss_diff; # define DAEMON_MUST_EXEC #endif -/* Nonzero means running Emacs without interactive terminal. */ -int noninteractive; +/* True means running Emacs without interactive terminal. */ +bool noninteractive; -/* Nonzero means remove site-lisp directories from load-path. */ -int no_site_lisp; +/* True means remove site-lisp directories from load-path. */ +bool no_site_lisp; /* Name for the server started by the daemon.*/ static char *daemon_name; @@ -299,16 +297,8 @@ section of the Emacs manual or the file BUGS.\n" /* Signal code for the fatal signal that was received. */ static int fatal_error_code; -/* Nonzero if handling a fatal error already. */ -int fatal_error_in_progress; - -#ifdef FORWARD_SIGNAL_TO_MAIN_THREAD -/* When compiled with GTK and running under Gnome, - multiple threads may be created. Keep track of our main - thread to make sure signals are delivered to it (see syssignal.h). */ - -pthread_t main_thread; -#endif +/* True if handling a fatal error already. */ +bool fatal_error_in_progress; #ifdef HAVE_NS /* NS autrelease pool, for memory management. */ @@ -318,13 +308,23 @@ static void *ns_pool; /* Handle bus errors, invalid instruction, etc. */ -#ifndef FLOAT_CATCH_SIGILL -static -#endif -void -fatal_error_signal (int sig) +static void +handle_fatal_signal (int sig) +{ + fatal_error_backtrace (sig, 10); +} + +static void +deliver_fatal_signal (int sig) +{ + handle_on_main_thread (sig, handle_fatal_signal); +} + +/* 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) { - SIGNAL_THREAD_CHECK (sig); fatal_error_code = sig; signal (sig, SIG_DFL); @@ -338,7 +338,8 @@ fatal_error_signal (int sig) if (sig == SIGTERM || sig == SIGHUP || sig == SIGINT) Fkill_emacs (make_number (sig)); - shut_down_emacs (sig, 0, Qnil); + shut_down_emacs (sig, Qnil); + emacs_backtrace (backtrace_limit); } /* Signal the same code; this time it will really be fatal. @@ -346,43 +347,44 @@ fatal_error_signal (int sig) going to send is probably blocked, so we have to unblock it if we want to really receive it. */ #ifndef MSDOS - sigunblock (sigmask (fatal_error_code)); + { + sigset_t unblocked; + sigemptyset (&unblocked); + sigaddset (&unblocked, fatal_error_code); + pthread_sigmask (SIG_UNBLOCK, &unblocked, 0); + } #endif kill (getpid (), fatal_error_code); + + /* This shouldn't be executed, but it prevents a warning. */ + exit (1); } #ifdef SIGDANGER /* Handler for SIGDANGER. */ -void -memory_warning_signal (int sig) +static void deliver_danger_signal (int); + +static void +handle_danger_signal (int sig) { - signal (sig, memory_warning_signal); - SIGNAL_THREAD_CHECK (sig); + struct sigaction action; + emacs_sigaction_init (&action, deliver_danger_signal); + sigaction (sig, &action, 0); malloc_warning ("Operating system warns that virtual memory is running low.\n"); /* It might be unsafe to call do_auto_save now. */ force_auto_save_soon (); } -#endif - -/* We define abort, rather than using it from the library, - so that GDB can return from a breakpoint here. - MSDOS has its own definition in msdos.c. */ -#if ! defined (DOS_NT) && ! defined (NO_ABORT) - -void -abort (void) +static void +deliver_danger_signal (int sig) { - kill (getpid (), SIGABRT); - /* This shouldn't be executed, but it prevents a warning. */ - exit (1); + handle_on_main_thread (sig, handle_danger_signal); } #endif - /* Code for dealing with Lisp access to the Unix command line. */ @@ -595,7 +597,7 @@ DEFINE_DUMMY_FUNCTION (__main) Too bad we can't just use getopt for all of this, but we don't have enough information to do it right. */ -static int +static bool argmatch (char **argv, int argc, const char *sstr, const char *lstr, int minlen, char **valptr, int *skipptr) { @@ -702,18 +704,19 @@ main (int argc, char **argv) Lisp_Object dummy; #endif char stack_bottom_variable; - int do_initial_setlocale; + bool do_initial_setlocale; int skip_args = 0; #ifdef HAVE_SETRLIMIT struct rlimit rlim; #endif - int no_loadup = 0; + bool no_loadup = 0; char *junk = 0; char *dname_arg = 0; #ifdef DAEMON_MUST_EXEC char dname_arg2[80]; #endif /* DAEMON_MUST_EXEC */ char *ch_to_dir; + struct sigaction fatal_error_action; #if GC_MARK_STACK stack_base = &dummy; @@ -872,20 +875,12 @@ main (int argc, char **argv) /* Arrange to get warning messages as memory fills up. */ memory_warnings (0, malloc_warning); - /* Call malloc at least once, to run the initial __malloc_hook. + /* Call malloc at least once, to run malloc_initialize_hook. Also call realloc and free for consistency. */ free (realloc (malloc (4), 4)); -# ifndef SYNC_INPUT - /* Arrange to disable interrupt input inside malloc etc. */ - uninterrupt_malloc (); -# endif /* not SYNC_INPUT */ #endif /* not SYSTEM_MALLOC */ -#ifdef FORWARD_SIGNAL_TO_MAIN_THREAD - main_thread = pthread_self (); -#endif /* FORWARD_SIGNAL_TO_MAIN_THREAD */ - #if defined (MSDOS) || defined (WINDOWSNT) /* We do all file input/output as binary files. When we need to translate newlines, we do that manually. */ @@ -1132,6 +1127,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem } init_signals (); + emacs_sigaction_init (&fatal_error_action, deliver_fatal_signal); /* Don't catch SIGHUP if dumping. */ if (1 @@ -1140,13 +1136,17 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem #endif ) { - sigblock (sigmask (SIGHUP)); /* In --batch mode, don't catch SIGHUP if already ignored. That makes nohup work. */ - if (! noninteractive - || signal (SIGHUP, SIG_IGN) != SIG_IGN) - signal (SIGHUP, fatal_error_signal); - sigunblock (sigmask (SIGHUP)); + bool catch_SIGHUP = !noninteractive; + if (!catch_SIGHUP) + { + struct sigaction old_action; + sigaction (SIGHUP, 0, &old_action); + catch_SIGHUP = old_action.sa_handler != SIG_IGN; + } + if (catch_SIGHUP) + sigaction (SIGHUP, &fatal_error_action, 0); } if ( @@ -1160,9 +1160,9 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem /* Don't catch these signals in batch mode if dumping. On some machines, this sets static data that would make signal fail to work right when the dumped Emacs is run. */ - signal (SIGQUIT, fatal_error_signal); - signal (SIGILL, fatal_error_signal); - signal (SIGTRAP, fatal_error_signal); + sigaction (SIGQUIT, &fatal_error_action, 0); + sigaction (SIGILL, &fatal_error_action, 0); + sigaction (SIGTRAP, &fatal_error_action, 0); #ifdef SIGUSR1 add_user_signal (SIGUSR1, "sigusr1"); #endif @@ -1170,68 +1170,73 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem add_user_signal (SIGUSR2, "sigusr2"); #endif #ifdef SIGABRT - signal (SIGABRT, fatal_error_signal); + sigaction (SIGABRT, &fatal_error_action, 0); #endif #ifdef SIGHWE - signal (SIGHWE, fatal_error_signal); + sigaction (SIGHWE, &fatal_error_action, 0); #endif #ifdef SIGPRE - signal (SIGPRE, fatal_error_signal); + sigaction (SIGPRE, &fatal_error_action, 0); #endif #ifdef SIGORE - signal (SIGORE, fatal_error_signal); + sigaction (SIGORE, &fatal_error_action, 0); #endif #ifdef SIGUME - signal (SIGUME, fatal_error_signal); + sigaction (SIGUME, &fatal_error_action, 0); #endif #ifdef SIGDLK - signal (SIGDLK, fatal_error_signal); + sigaction (SIGDLK, &fatal_error_action, 0); #endif #ifdef SIGCPULIM - signal (SIGCPULIM, fatal_error_signal); + sigaction (SIGCPULIM, &fatal_error_action, 0); #endif #ifdef SIGIOT /* This is missing on some systems - OS/2, for example. */ - signal (SIGIOT, fatal_error_signal); + sigaction (SIGIOT, &fatal_error_action, 0); #endif #ifdef SIGEMT - signal (SIGEMT, fatal_error_signal); + sigaction (SIGEMT, &fatal_error_action, 0); #endif - signal (SIGFPE, fatal_error_signal); + sigaction (SIGFPE, &fatal_error_action, 0); #ifdef SIGBUS - signal (SIGBUS, fatal_error_signal); + sigaction (SIGBUS, &fatal_error_action, 0); #endif - signal (SIGSEGV, fatal_error_signal); + sigaction (SIGSEGV, &fatal_error_action, 0); #ifdef SIGSYS - signal (SIGSYS, fatal_error_signal); + sigaction (SIGSYS, &fatal_error_action, 0); #endif /* May need special treatment on MS-Windows. See http://lists.gnu.org/archive/html/emacs-devel/2010-09/msg01062.html Please update the doc of kill-emacs, kill-emacs-hook, and NEWS if you change this. */ - if (noninteractive) signal (SIGINT, fatal_error_signal); - signal (SIGTERM, fatal_error_signal); + if (noninteractive) + sigaction (SIGINT, &fatal_error_action, 0); + sigaction (SIGTERM, &fatal_error_action, 0); #ifdef SIGXCPU - signal (SIGXCPU, fatal_error_signal); + sigaction (SIGXCPU, &fatal_error_action, 0); #endif #ifdef SIGXFSZ - signal (SIGXFSZ, fatal_error_signal); + sigaction (SIGXFSZ, &fatal_error_action, 0); #endif /* SIGXFSZ */ #ifdef SIGDANGER /* This just means available memory is getting low. */ - signal (SIGDANGER, memory_warning_signal); + { + struct sigaction action; + emacs_sigaction_init (&action, deliver_danger_signal); + sigaction (SIGDANGER, &action, 0); + } #endif #ifdef AIX /* 20 is SIGCHLD, 21 is SIGTTIN, 22 is SIGTTOU. */ - signal (SIGXCPU, fatal_error_signal); - signal (SIGIOINT, fatal_error_signal); - signal (SIGGRANT, fatal_error_signal); - signal (SIGRETRACT, fatal_error_signal); - signal (SIGSOUND, fatal_error_signal); - signal (SIGMSG, fatal_error_signal); + sigaction (SIGXCPU, &fatal_error_action, 0); + sigaction (SIGIOINT, &fatal_error_action, 0); + sigaction (SIGGRANT, &fatal_error_action, 0); + sigaction (SIGRETRACT, &fatal_error_action, 0); + sigaction (SIGSOUND, &fatal_error_action, 0); + sigaction (SIGMSG, &fatal_error_action, 0); #endif /* AIX */ } @@ -1607,7 +1612,6 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem init_fringe (); #endif /* HAVE_WINDOW_SYSTEM */ init_macros (); - init_floatfns (); init_window (); init_font (); @@ -1922,7 +1926,7 @@ sort_args (int argc, char **argv) } if (best < 0) - abort (); + emacs_abort (); /* Copy the highest priority remaining option, with its args, to NEW. Unless it is a duplicate of the previous one. */ @@ -1985,7 +1989,7 @@ all of which are called before Emacs is actually killed. */) x_clipboard_manager_save_all (); #endif - shut_down_emacs (0, 0, STRINGP (arg) ? arg : Qnil); + shut_down_emacs (0, STRINGP (arg) ? arg : Qnil); #ifdef HAVE_NS ns_release_autorelease_pool (ns_pool); @@ -2021,7 +2025,7 @@ all of which are called before Emacs is actually killed. */) and Fkill_emacs. */ void -shut_down_emacs (int sig, int no_x, Lisp_Object stuff) +shut_down_emacs (int sig, Lisp_Object stuff) { /* Prevent running of hooks from now on. */ Vrun_hooks = Qnil; @@ -2038,7 +2042,7 @@ shut_down_emacs (int sig, int no_x, 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 @@ -2056,23 +2060,10 @@ shut_down_emacs (int sig, int no_x, Lisp_Object stuff) unlock_all_files (); #endif -#if 0 /* This triggers a bug in XCloseDisplay and is not needed. */ -#ifdef HAVE_X_WINDOWS - /* It's not safe to call intern here. Maybe we are crashing. */ - if (!noninteractive && SYMBOLP (Vinitial_window_system) - && SCHARS (SYMBOL_NAME (Vinitial_window_system)) == 1 - && SREF (SYMBOL_NAME (Vinitial_window_system), 0) == 'x' - && ! no_x) - Fx_close_current_connection (); -#endif /* HAVE_X_WINDOWS */ -#endif - -#ifdef SIGIO /* There is a tendency for a SIGIO signal to arrive within exit, and cause a SIGHUP because the input descriptor is already closed. */ unrequest_sigio (); - signal (SIGIO, SIG_IGN); -#endif + ignore_sigio (); #ifdef WINDOWSNT term_ntproc (); @@ -2178,12 +2169,6 @@ You must run Emacs in batch mode in order to dump it. */) memory_warnings (my_edata, malloc_warning); } #endif /* not WINDOWSNT */ -#if defined (HAVE_PTHREAD) && !defined SYNC_INPUT - /* Pthread may call malloc before main, and then we will get an endless - loop, because pthread_self (see alloc.c) calls malloc the first time - it is called on some systems. */ - reset_malloc_hooks (); -#endif #endif /* not SYSTEM_MALLOC */ #ifdef DOUG_LEA_MALLOC malloc_state_ptr = malloc_get_state (); @@ -2258,7 +2243,7 @@ decode_env_path (const char *evarname, const char *defalt) const char *path, *p; Lisp_Object lpath, element, tem; #ifdef WINDOWSNT - int defaulted = 0; + bool defaulted = 0; const char *emacs_dir = egetenv ("emacs_dir"); static const char *emacs_dir_env = "%emacs_dir%/"; const size_t emacs_dir_len = strlen (emacs_dir_env); @@ -2354,7 +2339,7 @@ from the parent process and its tty file descriptors. */) (void) { int nfd; - int err = 0; + bool err = 0; if (!IS_DAEMON) error ("This function can only be called if emacs is run as a daemon"); |