mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-06-14 04:21:24 +00:00
keyboard.c: Allow SIGINT to quit in batch mode, instead of exit
In terminal sessions, SIGINT is turned into a `quit` ELisp signal, but in batch it has traditionally killed Emacs. It can be very useful to cause a `quit` from outside the process when running in batch (e.g. for "batch" sessions that provide a REPL via stdin/out), so add a new var 'kill-emacs-on-sigint' to control that behavior. (bug#80942) * src/keyboard.c (handle_interrupt_signal): Obey `kill_emacs_on_sigint`. (init_keyboard): Use `deliver_interrupt_signal` for SIGINT also for batch sessions. (syms_of_keyboard): New variable `kill_emacs_on_sigint`. * test/src/keyboard-tests.el (keyboard-sigint-to-quit): New test. * doc/emacs/cmdargs.texi (Initial Options): Mention the effect of `kill-emacs-on-sigint` in batch mode.
This commit is contained in:
parent
9c0a699c59
commit
a952324e9b
4 changed files with 67 additions and 13 deletions
|
|
@ -260,9 +260,14 @@ on. To invoke a Lisp program, use the @samp{-batch} option in
|
|||
conjunction with one or more of @samp{-l}, @samp{-f} or @samp{--eval}
|
||||
(@pxref{Action Arguments}). @xref{Command Example}, for an example.
|
||||
|
||||
@vindex kill-emacs-on-sigint
|
||||
In batch mode, Emacs does not display the text being edited, and the
|
||||
standard terminal interrupt characters such as @kbd{C-z} and @kbd{C-c}
|
||||
have their usual effect. Emacs functions that normally print a
|
||||
have their usual effect: for @kbd{C-c} that effect is either to
|
||||
exit Emacs or to signal @code{quit}, depending on the variable
|
||||
@code{kill-emacs-on-sigint}.
|
||||
|
||||
Emacs functions that normally print a
|
||||
message in the echo area will print to either the standard output
|
||||
stream (@code{stdout}) or the standard error stream (@code{stderr})
|
||||
instead. (To be precise, functions like @code{prin1}, @code{princ}
|
||||
|
|
|
|||
8
etc/NEWS
8
etc/NEWS
|
|
@ -4593,6 +4593,14 @@ is a proper list, in which case the list will be returned as is,
|
|||
otherwise the function will return the object wrapped in a
|
||||
singleton list.
|
||||
|
||||
---
|
||||
** In batch mode, 'C-c' (i.e. SIGINT) can either 'quit' or kill Emacs.
|
||||
By default it kills Emacs, as before, but 'kill-emacs-on-sigint'
|
||||
can be set to nil to change that.
|
||||
The response to SIGINT in interactive sessions is unaffected,
|
||||
e.g. in a normal GUI session it still kills Emacs whereas in a terminal
|
||||
it causes 'quit' since it is used for 'C-g'.
|
||||
|
||||
|
||||
* Changes in Emacs 31.1 on Non-Free Operating Systems
|
||||
|
||||
|
|
|
|||
|
|
@ -12543,11 +12543,17 @@ handle_interrupt_signal (int sig)
|
|||
struct terminal *terminal = get_named_terminal (dev_tty);
|
||||
if (!terminal)
|
||||
{
|
||||
/* If there are no frames there, let's pretend that we are a
|
||||
well-behaving UN*X program and quit. We must not call Lisp
|
||||
/* There are no frames, so either 'quit' or exit.
|
||||
If 'kill-emacs-on-sigint', pretend that we are a
|
||||
well-behaving UN*X program and exit. We must not call Lisp
|
||||
in a signal handler, so tell maybe_quit to exit when it is
|
||||
safe. */
|
||||
Vquit_flag = Qkill_emacs;
|
||||
Vquit_flag = (kill_emacs_on_sigint
|
||||
/* Don't risk running ELisp code while shutting down
|
||||
and limit the effect of 'kill_emacs_on_sigint'
|
||||
to batch sessions. */
|
||||
|| NILP (Vrun_hooks) || !noninteractive
|
||||
? Qkill_emacs : Qt);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -13224,17 +13230,18 @@ init_keyboard (void)
|
|||
it for the initial terminal since there is no window system there. */
|
||||
init_kboard (current_kboard, Qnil);
|
||||
|
||||
/* Before multi-tty support, these handlers used to be installed
|
||||
only if the current session was a tty session. Now an Emacs
|
||||
session may have multiple display types, so we always handle
|
||||
SIGINT. There is special code in handle_interrupt_signal to exit
|
||||
Emacs on SIGINT when there are no termcap frames on the
|
||||
controlling terminal. */
|
||||
struct sigaction action;
|
||||
emacs_sigaction_init (&action, deliver_interrupt_signal);
|
||||
sigaction (SIGINT, &action, 0);
|
||||
|
||||
if (!noninteractive)
|
||||
{
|
||||
/* Before multi-tty support, these handlers used to be installed
|
||||
only if the current session was a tty session. Now an Emacs
|
||||
session may have multiple display types, so we always handle
|
||||
SIGINT. There is special code in handle_interrupt_signal to exit
|
||||
Emacs on SIGINT when there are no termcap frames on the
|
||||
controlling terminal. */
|
||||
struct sigaction action;
|
||||
emacs_sigaction_init (&action, deliver_interrupt_signal);
|
||||
sigaction (SIGINT, &action, 0);
|
||||
#ifndef DOS_NT
|
||||
/* For systems with SysV TERMIO, C-g is set up for both SIGINT and
|
||||
SIGQUIT and we can't tell which one it will give us. */
|
||||
|
|
@ -13401,6 +13408,12 @@ syms_of_keyboard (void)
|
|||
doc: /* Message displayed by `normal-top-level'. */);
|
||||
Vinternal__top_level_message = regular_top_level_message;
|
||||
|
||||
DEFVAR_BOOL ("kill-emacs-on-sigint", kill_emacs_on_sigint,
|
||||
doc: /* If non-nil, a SIGINT event causes Emacs to exit.
|
||||
If nil, a SIGINT event causes a `quit` signal instead.
|
||||
This is effective only in `noninteractive' sessions. */);
|
||||
kill_emacs_on_sigint = true;
|
||||
|
||||
/* Tool-bars. */
|
||||
DEFSYM (QCimage, ":image");
|
||||
DEFSYM (Qhelp_echo, "help-echo");
|
||||
|
|
|
|||
|
|
@ -81,6 +81,34 @@
|
|||
(should-error (read-event "foo: "))
|
||||
(should-error (read-char-exclusive "foo: "))))
|
||||
|
||||
(ert-deftest keyboard-sigint-to-quit () ;; bug#80942
|
||||
(with-temp-buffer
|
||||
(let* ((exit-msg "Exit via Quit")
|
||||
(proc
|
||||
(make-process
|
||||
:name "keyboard-sigint-to-quit"
|
||||
:buffer (current-buffer)
|
||||
:command
|
||||
`(,(expand-file-name invocation-name invocation-directory)
|
||||
"-Q" "--batch" "--eval"
|
||||
,(prin1-to-string
|
||||
`(progn (setq kill-emacs-on-sigint nil)
|
||||
(message "Ready!")
|
||||
(condition-case nil
|
||||
(dotimes (_ 3) (sit-for 1))
|
||||
(quit (message "%s" ,exit-msg)))))))))
|
||||
(while (progn (accept-process-output proc 1.0)
|
||||
(goto-char (point-min))
|
||||
(not (re-search-forward "Ready!" nil t)))
|
||||
) ;; (message "Waiting for subprocess to be ready")
|
||||
;; (message "Subprocess is ready")
|
||||
(interrupt-process proc)
|
||||
(while (prog1 (memq (process-status proc) '(run))
|
||||
(accept-process-output proc 1.0))
|
||||
) ;; (message "Waiting for subprocess to exit")
|
||||
(goto-char (point-min))
|
||||
(should (re-search-forward exit-msg nil t)))))
|
||||
|
||||
;;; Tests for `read-key-sequence' code paths.
|
||||
|
||||
;;;; Helpers
|
||||
|
|
|
|||
Loading…
Reference in a new issue