summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Mackenzie <acm@muc.de>2022-02-02 20:35:39 +0000
committerAlan Mackenzie <acm@muc.de>2022-02-02 20:35:39 +0000
commitaa795a6223c31ec8804f2824c435dba3091c115f (patch)
tree3ab30ccf54019c835d584ae9ae72ec6341e2b123
parentb6a51e05c9714827737708ce7fb2068f285005ce (diff)
downloademacs-aa795a6223c31ec8804f2824c435dba3091c115f.tar.gz
emacs-aa795a6223c31ec8804f2824c435dba3091c115f.tar.bz2
emacs-aa795a6223c31ec8804f2824c435dba3091c115f.zip
New file lisp/emacs-lisp/debug-early.el for backtraces in early bootstrap
This is also used in batch mode in general. * lisp/debug-early.el (debug-early-backtrace, debug-early): New functions. * lisp/loadup.el (top level): Load debug-early.el as first file. * src/eval.c (signal_or_quit): Remove the condition in the batch mode section of not being in dumping or bootstrap, since it is no longer needed. Test that 'debug-early's symbol-function is bound. Ensure there is enough working space in specpdl and eval_depth. (syms_of_eval): New DEFSYM for Qdebug_early. Initialise Vdebugger to Qdebug_early rather than Qnil.
-rw-r--r--lisp/emacs-lisp/debug-early.el77
-rw-r--r--lisp/loadup.el1
-rw-r--r--src/eval.c18
3 files changed, 88 insertions, 8 deletions
diff --git a/lisp/emacs-lisp/debug-early.el b/lisp/emacs-lisp/debug-early.el
new file mode 100644
index 00000000000..718000bfa4c
--- /dev/null
+++ b/lisp/emacs-lisp/debug-early.el
@@ -0,0 +1,77 @@
+;;; debug-early.el --- Dump a Lisp backtrace without frills -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Author: Alan Mackenzie <acm@muc.de>
+;; Maintainer: emacs-devel@gnu.org
+;; Keywords: internal, backtrace, bootstrap.
+;; Package: emacs
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This file dumps a backtrace on stderr when an error is thrown.
+;; It has no dependencies on any Lisp libraries and is thus suitable
+;; for generating backtraces in the early parts of bootstrapping. It
+;; is also good for generating backtraces in batch mode in general.
+
+(defalias 'debug-early-backtrace
+ #'(lambda ()
+ "Print a trace of Lisp function calls currently active.
+The output stream used is the value of `standard-output'.
+
+This is a simplified version of the standard `backtrace'
+function, intended for use in debugging the early parts
+of the build process."
+ (princ "\n")
+ (mapbacktrace
+ #'(lambda (evald func args _flags)
+ (let ((args args))
+ (if evald
+ (progn
+ (princ " ")
+ (prin1 func)
+ (princ "(")
+ (while args
+ (prin1 (car args))
+ (setq args (cdr args))
+ (if args
+ (princ " ")))
+ (princ ")\n"))
+ (while args
+ (princ " ")
+ (prin1 (car args))
+ (princ "\n")
+ (setq args (cdr args)))))))))
+
+(defalias 'debug-early
+ #'(lambda (&rest args)
+ "Print a trace of Lisp function calls currently active.
+The output stream used is the value of `standard-output'.
+
+There should be two ARGS, the symbol `error' and a cons of
+the error symbol and its data.
+
+This is a simplified version of `debug', intended for use
+in debugging the early parts of the build process."
+ (princ "\nError: ")
+ (prin1 (car (car (cdr args)))) ; The error symbol.
+ (princ " ")
+ (prin1 (cdr (car (cdr args)))) ; The error data.
+ (debug-early-backtrace)))
+
+;;; debug-early.el ends here.
diff --git a/lisp/loadup.el b/lisp/loadup.el
index 1be73a2090d..81172c584d7 100644
--- a/lisp/loadup.el
+++ b/lisp/loadup.el
@@ -128,6 +128,7 @@
(set-buffer "*scratch*")
(setq buffer-undo-list t)
+(load "emacs-lisp/debug-early")
(load "emacs-lisp/byte-run")
(load "emacs-lisp/backquote")
(load "subr")
diff --git a/src/eval.c b/src/eval.c
index 3e648ed6216..c87b1bc704c 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1873,18 +1873,19 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit)
}
/* If we're in batch mode, print a backtrace unconditionally to help
- with debugging. Make sure to use `debug' unconditionally to not
- interfere with ERT or other packages that install custom
- debuggers. Don't try to call the debugger while dumping or
- bootstrapping, it wouldn't work anyway. */
+ with debugging. Make sure to use `debug-early' unconditionally
+ to not interfere with ERT or other packages that install custom
+ debuggers. */
if (!debugger_called && !NILP (error_symbol)
&& (NILP (clause) || EQ (h->tag_or_ch, Qerror))
&& noninteractive && backtrace_on_error_noninteractive
- && !will_dump_p () && !will_bootstrap_p ()
- && NILP (Vinhibit_debugger))
+ && NILP (Vinhibit_debugger)
+ && !NILP (Ffboundp (Qdebug_early)))
{
+ max_ensure_room (&max_lisp_eval_depth, lisp_eval_depth, 100);
+ max_ensure_room (&max_specpdl_size, SPECPDL_INDEX (), 200);
ptrdiff_t count = SPECPDL_INDEX ();
- specbind (Qdebugger, Qdebug);
+ specbind (Qdebugger, Qdebug_early);
call_debugger (list2 (Qerror, Fcons (error_symbol, data)));
unbind_to (count, Qnil);
}
@@ -4399,6 +4400,7 @@ before making `inhibit-quit' nil. */);
DEFSYM (Qclosure, "closure");
DEFSYM (QCdocumentation, ":documentation");
DEFSYM (Qdebug, "debug");
+ DEFSYM (Qdebug_early, "debug-early");
DEFVAR_LISP ("inhibit-debugger", Vinhibit_debugger,
doc: /* Non-nil means never enter the debugger.
@@ -4453,7 +4455,7 @@ If due to frame exit, args are `exit' and the value being returned;
If due to error, args are `error' and a list of the args to `signal'.
If due to `apply' or `funcall' entry, one arg, `lambda'.
If due to `eval' entry, one arg, t. */);
- Vdebugger = Qnil;
+ Vdebugger = Qdebug_early;
DEFVAR_LISP ("signal-hook-function", Vsignal_hook_function,
doc: /* If non-nil, this is a function for `signal' to call.