From fe000236cf278a469adbf27e2184f823f7e12587 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Thu, 9 Nov 2023 10:33:28 +0200 Subject: [PATCH] Improve documentation of signaling errors in batch mode * doc/lispref/control.texi (Signaling Errors) (Processing of Errors): * doc/lispref/os.texi (Batch Mode): * doc/lispref/debugging.texi (Invoking the Debugger): * lisp/emacs-lisp/debug.el (debug): * src/eval.c (Fsignal): * lisp/subr.el (error): Document more prominently that signaling an unhandled error in batch mode kills Emacs. Better documentation of backtrace in batch mode. --- doc/lispref/control.texi | 19 ++++++++++++----- doc/lispref/debugging.texi | 24 ++++++++++++++++----- doc/lispref/os.texi | 43 ++++++++++++++++++++++++++------------ lisp/emacs-lisp/debug.el | 7 +++++++ lisp/subr.el | 4 ++++ src/eval.c | 4 ++++ 6 files changed, 78 insertions(+), 23 deletions(-) diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi index 3aee9dd80e4..84196c9116a 100644 --- a/doc/lispref/control.texi +++ b/doc/lispref/control.texi @@ -1882,6 +1882,9 @@ verbatim, don't just write @code{(error @var{string})}. If @var{string} @var{string} contains @samp{%}, @samp{`}, or @samp{'} it may be reformatted, with undesirable results. Instead, use @code{(error "%s" @var{string})}. + +When @code{noninteractive} is non-@code{nil} (@pxref{Batch Mode}), +this function kills Emacs if the signaled error has no handler. @end defun @defun signal error-symbol data @@ -1915,6 +1918,9 @@ variable to a list of the form @code{(@var{error-symbol} .@: The function @code{signal} never returns. @c (though in older Emacs versions it sometimes could). +If the error @var{error-symbol} has no handler, and +@code{noninteractive} is non-@code{nil} (@pxref{Batch Mode}), +this function eventually kills Emacs. @example @group @@ -1979,11 +1985,14 @@ function which called the primitive that signaled the error. @end defvar @cindex @code{debug-on-error} use -An error that has no explicit handler may call the Lisp debugger. The -debugger is enabled if the variable @code{debug-on-error} (@pxref{Error -Debugging}) is non-@code{nil}. Unlike error handlers, the debugger runs -in the environment of the error, so that you can examine values of -variables precisely as they were at the time of the error. +An error that has no explicit handler may call the Lisp debugger +(@pxref{Invoking the Debugger}). The debugger is enabled if the +variable @code{debug-on-error} (@pxref{Error Debugging}) is +non-@code{nil}. Unlike error handlers, the debugger runs in the +environment of the error, so that you can examine values of variables +precisely as they were at the time of the error. In batch mode +(@pxref{Batch Mode}), the Emacs process then normally exits with a +non-zero exit status. @node Handling Errors @subsubsection Writing Code to Handle Errors diff --git a/doc/lispref/debugging.texi b/doc/lispref/debugging.texi index 169e3ac37d3..1246b3ff57a 100644 --- a/doc/lispref/debugging.texi +++ b/doc/lispref/debugging.texi @@ -629,11 +629,18 @@ This is a list of functions that are set to break on entry by means of to invoke the debugger. @deffn Command debug &rest debugger-args -This function enters the debugger. It switches buffers to a buffer -named @file{*Backtrace*} (or @file{*Backtrace*<2>} if it is the second -recursive entry to the debugger, etc.), and fills it with information -about the stack of Lisp function calls. It then enters a recursive -edit, showing the backtrace buffer in Debugger mode. +This function enters the debugger. In interactive sessions, it +switches to a buffer named @file{*Backtrace*} (or +@file{*Backtrace*<2>} if it is the second recursive entry to the +debugger, etc.), and fills it with information about the stack of Lisp +function calls. It then enters a recursive edit, showing the +backtrace buffer in Debugger mode. In batch mode (more generally, +when @code{noninteractive} is non-@code{nil}, @pxref{Batch Mode}), +this function shows the Lisp backtrace on the standard error stream, +and then kills Emacs, causing it to exit with a non-zero exit code +(@pxref{Killing Emacs}). Binding +@code{backtrace-on-error-noninteractive} to @code{nil} suppresses the +backtrace in batch mode, see below. The Debugger mode @kbd{c}, @kbd{d}, @kbd{j}, and @kbd{r} commands exit the recursive edit; then @code{debug} switches back to the previous @@ -717,6 +724,13 @@ under which @code{debug} is called. @end table @end deffn +@defvar backtrace-on-error-noninteractive +If this variable is non-@code{nil}, the default, entering the debugger +in batch mode shows the backtrace of Lisp functions calls. Binding +the variable to the @code{nil} value suppresses the backtrace and +shows only the error message. +@end defvar + @node Internals of Debugger @subsection Internals of the Debugger diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi index ea27af8edb2..1995fd9fb2a 100644 --- a/doc/lispref/os.texi +++ b/doc/lispref/os.texi @@ -2736,6 +2736,35 @@ way to specify the programs to run is with @samp{-l @var{file}}, which loads the library named @var{file}, or @samp{-f @var{function}}, which calls @var{function} with no arguments, or @samp{--eval=@var{form}}. +@defvar noninteractive +This variable is non-@code{nil} when Emacs is running in batch mode. +@end defvar + + If the specified Lisp program signals an unhandled error in batch +mode, Emacs exits with a non-zero exit status after invoking the Lisp +debugger which shows the Lisp backtrace (@pxref{Invoking the +Debugger}) on the standard error stream: + +@example +$ emacs -Q --batch --eval '(error "foo")'; echo $? + +@group +Error: error ("foo") +mapbacktrace(#f(compiled-function (evald func args flags) #)) +debug-early-backtrace() +debug-early(error (error "foo")) +signal(error ("foo")) +error("foo") +eval((error "foo") t) +command-line-1(("--eval" "(error \"foo\")")) +command-line() +normal-top-level() +@end group +foo +255 +@end example + Any Lisp program output that would normally go to the echo area, either using @code{message}, or using @code{prin1}, etc., with @code{t} as the stream (@pxref{Output Streams}), goes instead to @@ -2753,6 +2782,7 @@ if it is non-@code{nil}; this can be overridden by binding @code{coding-system-for-write} to a coding system of you choice (@pxref{Explicit Encoding}). +@vindex gc-cons-percentage@r{, in batch mode} In batch mode, Emacs will enlarge the value of the @code{gc-cons-percentage} variable from the default of @samp{0.1} up to @samp{1.0}. Batch jobs that are supposed to run for a long time @@ -2760,19 +2790,6 @@ should adjust the limit back down again, because this means that less garbage collection will be performed by default (and more memory consumed). -@defvar noninteractive -This variable is non-@code{nil} when Emacs is running in batch mode. -@end defvar - -If Emacs exits due to signaling an error in batch mode, the exit -status of the Emacs command is non-zero: - -@example -$ emacs -Q --batch --eval '(error "foo")'; echo $? -foo -255 -@end example - @node Session Management @section Session Management @cindex session manager diff --git a/lisp/emacs-lisp/debug.el b/lisp/emacs-lisp/debug.el index dc23b071f0d..5411088189d 100644 --- a/lisp/emacs-lisp/debug.el +++ b/lisp/emacs-lisp/debug.el @@ -158,6 +158,13 @@ where CAUSE can be: ;;;###autoload (defun debug (&rest args) "Enter debugger. \\`\\[debugger-continue]' returns from the debugger. + +In interactive sessions, this switches to a backtrace buffer and shows +the Lisp backtrace of function calls there. In batch mode (more accurately, +when `noninteractive' is non-nil), it shows the Lisp backtrace on the +standard error stream (unless `backtrace-on-error-noninteractive' is nil), +and then kills Emacs, causing it to exit with a negative exit code. + Arguments are mainly for use when this is called from the internals of the evaluator. diff --git a/lisp/subr.el b/lisp/subr.el index d5c461346cb..88c2166b1c4 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -418,6 +418,10 @@ Also see `ignore'." Errors cause entry to the debugger when `debug-on-error' is non-nil. This can be overridden by `debug-ignored-errors'. +When `noninteractive' is non-nil (in particular, in batch mode), an +unhandled error calls `kill-emacs', which terminates the Emacs +session with a non-zero exit code. + To signal with MESSAGE without interpreting format characters like `%', `\\=`' and `\\='', use (error \"%s\" MESSAGE). In Emacs, the convention is that error messages start with a capital diff --git a/src/eval.c b/src/eval.c index 2dd0c356e88..3a01617f702 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1666,6 +1666,10 @@ DEFUN ("signal", Fsignal, Ssignal, 2, 2, 0, doc: /* Signal an error. Args are ERROR-SYMBOL and associated DATA. This function does not return. +When `noninteractive' is non-nil (in particular, in batch mode), an +unhandled error calls `kill-emacs', which terminates the Emacs +session with a non-zero exit code. + An error symbol is a symbol with an `error-conditions' property that is a list of condition names. The symbol should be non-nil. A handler for any of those names will get to handle this signal. -- 2.39.2