diff options
author | Andreas Schwab <[email protected]> | 2011-12-04 10:26:30 +0100 |
---|---|---|
committer | Andreas Schwab <[email protected]> | 2011-12-04 10:26:30 +0100 |
commit | 6c07aac2835c5ec4462fedb267f1bba5bb3cadc5 (patch) | |
tree | 4b8a0f5a7728830f323014ea541d1ec3c41c678b /src | |
parent | c80e3b4aed2e70eb6d8445d786c0df770094e9e1 (diff) |
Don't call Lisp in signal handler
* emacs.c (Qkill_emacs): Define.
(syms_of_emacs): Initialize it.
* keyboard.c (interrupt_signal): Don't call Fkill_emacs here, set
Qquit_flag to `kill-emacs' instead.
(quit_throw_to_read_char): Add parameter `from_signal'. All
callers changed. Call Fkill_emacs if requested and safe.
* lisp.h (QUIT): Call Fkill_emacs if requested.
Diffstat (limited to 'src')
-rw-r--r-- | src/ChangeLog | 10 | ||||
-rw-r--r-- | src/emacs.c | 3 | ||||
-rw-r--r-- | src/keyboard.c | 29 | ||||
-rw-r--r-- | src/lisp.h | 8 |
4 files changed, 36 insertions, 14 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 6a13bd8726..a1d5cc9d5b 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,13 @@ +2011-12-04 Andreas Schwab <[email protected]> + + * emacs.c (Qkill_emacs): Define. + (syms_of_emacs): Initialize it. + * keyboard.c (interrupt_signal): Don't call Fkill_emacs here, set + Qquit_flag to `kill-emacs' instead. + (quit_throw_to_read_char): Add parameter `from_signal'. All + callers changed. Call Fkill_emacs if requested and safe. + * lisp.h (QUIT): Call Fkill_emacs if requested. + 2011-12-03 Jan Djärv <[email protected]> * widget.c (update_wm_hints): Return if wmshell is null. diff --git a/src/emacs.c b/src/emacs.c index 529fa35a5b..6bfc0dc60d 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -154,6 +154,8 @@ Lisp_Object Qfile_name_handler_alist; Lisp_Object Qrisky_local_variable; +Lisp_Object Qkill_emacs; + /* If non-zero, 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; @@ -2394,6 +2396,7 @@ syms_of_emacs (void) { DEFSYM (Qfile_name_handler_alist, "file-name-handler-alist"); DEFSYM (Qrisky_local_variable, "risky-local-variable"); + DEFSYM (Qkill_emacs, "kill-emacs"); #ifndef CANNOT_DUMP defsubr (&Sdump_emacs); diff --git a/src/keyboard.c b/src/keyboard.c index 7da0348cb2..a114e495cf 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -464,7 +464,7 @@ static void input_available_signal (int signo); static Lisp_Object (Fcommand_execute) (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object); static void handle_interrupt (void); -static void quit_throw_to_read_char (void) NO_RETURN; +static void quit_throw_to_read_char (int) NO_RETURN; static void timer_start_idle (void); static void timer_stop_idle (void); static void timer_resume_idle (void); @@ -653,7 +653,7 @@ echo_now (void) echo_kboard = current_kboard; if (waiting_for_input && !NILP (Vquit_flag)) - quit_throw_to_read_char (); + quit_throw_to_read_char (0); } /* Turn off echoing, for the start of a new command. */ @@ -3817,7 +3817,7 @@ kbd_buffer_get_event (KBOARD **kbp, /* If the quit flag is set, then read_char will return quit_char, so that counts as "available input." */ if (!NILP (Vquit_flag)) - quit_throw_to_read_char (); + quit_throw_to_read_char (0); /* One way or another, wait until input is available; then, if interrupt handlers have not read it, read it now. */ @@ -10824,7 +10824,7 @@ set_waiting_for_input (struct timeval *time_to_clear) /* If handle_interrupt was called before and buffered a C-g, make it run again now, to avoid timing error. */ if (!NILP (Vquit_flag)) - quit_throw_to_read_char (); + quit_throw_to_read_char (0); } void @@ -10839,7 +10839,7 @@ clear_waiting_for_input (void) If we have a frame on the controlling tty, we assume that the SIGINT was generated by C-g, so we call handle_interrupt. - Otherwise, the handler kills Emacs. */ + Otherwise, tell QUIT to kill Emacs. */ static void interrupt_signal (int signalnum) /* If we don't have an argument, some */ @@ -10856,12 +10856,10 @@ interrupt_signal (int signalnum) /* If we don't have an argument, some */ if (!terminal) { /* If there are no frames there, let's pretend that we are a - well-behaving UN*X program and quit. We cannot do that while - GC is in progress, though. */ - if (!gc_in_progress && !waiting_for_input) - Fkill_emacs (Qnil); - else - Vquit_flag = Qt; + well-behaving UN*X program and quit. We must not call Lisp + in a signal handler, so tell QUIT to exit when it is + safe. */ + Vquit_flag = Qkill_emacs; } else { @@ -11010,15 +11008,20 @@ handle_interrupt (void) separate event loop thread like W32. */ #ifndef HAVE_NS if (waiting_for_input && !echoing) - quit_throw_to_read_char (); + quit_throw_to_read_char (1); #endif } /* Handle a C-g by making read_char return C-g. */ static void -quit_throw_to_read_char (void) +quit_throw_to_read_char (int from_signal) { + /* When not called from a signal handler it is safe to call + Lisp. */ + if (!from_signal && EQ (Vquit_flag, Qkill_emacs)) + Fkill_emacs (Qnil); + sigfree (); /* Prevent another signal from doing this before we finish. */ clear_waiting_for_input (); diff --git a/src/lisp.h b/src/lisp.h index e645fbd65a..969923b7cf 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -2128,7 +2128,10 @@ extern char *stack_bottom; Exception: if you set immediate_quit to nonzero, then the handler that responds to the C-g does the quit itself. This is a good thing to do around a loop that has no side effects - and (in particular) cannot call arbitrary Lisp code. */ + and (in particular) cannot call arbitrary Lisp code. + + If quit-flag is set to `kill-emacs' the SIGINT handler has received + a request to exit Emacs when it is safe to do. */ #ifdef SYNC_INPUT extern void process_pending_signals (void); @@ -2146,6 +2149,8 @@ extern int pending_signals; { \ Lisp_Object flag = Vquit_flag; \ Vquit_flag = Qnil; \ + if (EQ (flag, Qkill_emacs)) \ + Fkill_emacs (Qnil); \ if (EQ (Vthrow_on_input, flag)) \ Fthrow (Vthrow_on_input, Qt); \ Fsignal (Qquit, Qnil); \ @@ -3291,6 +3296,7 @@ extern Lisp_Object Qfile_name_handler_alist; #ifdef FLOAT_CATCH_SIGILL extern void fatal_error_signal (int); #endif +extern Lisp_Object Qkill_emacs; EXFUN (Fkill_emacs, 1) NO_RETURN; #if HAVE_SETLOCALE void fixup_locale (void); |