From: Alan Mackenzie Date: Wed, 2 Feb 2022 20:35:39 +0000 (+0000) Subject: New file lisp/emacs-lisp/debug-early.el for backtraces in early bootstrap X-Git-Tag: emacs-29.0.90~2572 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=aa795a6223c31ec8804f2824c435dba3091c115f;p=emacs.git 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. --- 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 +;; 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 . + +;;; 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.