Don't call Lisp in signal handler
authorAndreas Schwab <schwab@linux-m68k.org>
Sun, 4 Dec 2011 09:26:30 +0000 (10:26 +0100)
committerAndreas Schwab <schwab@linux-m68k.org>
Sun, 4 Dec 2011 09:26:30 +0000 (10:26 +0100)
* 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.

src/ChangeLog
src/emacs.c
src/keyboard.c
src/lisp.h

index 6a13bd8..a1d5cc9 100644 (file)
@@ -1,3 +1,13 @@
+2011-12-04  Andreas Schwab  <schwab@linux-m68k.org>
+
+       * 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  <jan.h.d@swipnet.se>
 
        * widget.c (update_wm_hints): Return if wmshell is null.
index 529fa35..6bfc0dc 100644 (file)
@@ -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);
index 7da0348..a114e49 100644 (file)
@@ -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 ();
index e645fbd..969923b 100644 (file)
@@ -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);