summaryrefslogtreecommitdiff
path: root/src/emacs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emacs.c')
-rw-r--r--src/emacs.c235
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");