Backtrace printing in batch mode ignores all customizations

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Backtrace printing in batch mode ignores all customizations

Paul Pogonyshev-2
Apparently it is because of this commit:

7228488effa78dcb75284cb6d247b24804e0e7f5
Author:     Stefan Monnier <[hidden email]>
AuthorDate: 2018-04-02 00:23:20 -0400
[...]

* lisp/emacs-lisp/debug.el (debug): Don't hang upon error in initial-frame.

[...]
+   ((and (eq t (framep (selected-frame)))
+         (equal "initial_terminal" (terminal-name)))
+    ;; We're in the initial-frame (where `message' just outputs to stdout) so
+    ;; there's no tty or GUI frame to display the backtrace and interact with
+    ;; it: just dump a backtrace to stdout.
+    ;; This happens for example while handling an error in code from
+    ;; early-init.el with --debug-init.
+    (message "Error: %S" args)
[...]

The condition seems to always be true when `noninteractive' is t. Is
this intentional? It appears to mean that all debug/backtrace
customizations in batch mode are meaningless, since debugger just goes
the "failsafe" route and prints backtrace with simple `message' calls
now.

Please CC me, I'm not subscribed.

Paul

Reply | Threaded
Open this post in threaded view
|

Re: Backtrace printing in batch mode ignores all customizations

Eli Zaretskii
> From: Paul Pogonyshev <[hidden email]>
> Date: Mon, 16 Dec 2019 23:34:42 +0100
>
> +   ((and (eq t (framep (selected-frame)))
> +         (equal "initial_terminal" (terminal-name)))
> +    ;; We're in the initial-frame (where `message' just outputs to stdout) so
> +    ;; there's no tty or GUI frame to display the backtrace and interact with
> +    ;; it: just dump a backtrace to stdout.
> +    ;; This happens for example while handling an error in code from
> +    ;; early-init.el with --debug-init.
> +    (message "Error: %S" args)
> [...]
>
> The condition seems to always be true when `noninteractive' is t. Is
> this intentional? It appears to mean that all debug/backtrace
> customizations in batch mode are meaningless, since debugger just goes
> the "failsafe" route and prints backtrace with simple `message' calls
> now.

Can you please elaborate about the debug/backtrace customizations you
did, which are bypassed due to this code?  What are those
customizations supposed to do?

Reply | Threaded
Open this post in threaded view
|

Re: Backtrace printing in batch mode ignores all customizations

Paul Pogonyshev-2
It's not really about _my_ customizations. Basically, this "failsafe"
mode in `debug' bypasses even e.g. built-in Emacs
`debugger-print-function'.

Here is an example (it has nothing to do with `registry', I just
needed some EIEIO class to illustrate):

$ emacs -Q --batch --eval "(let ((debug-on-error t)) (require
'registry) (defun foo (x) bar) (foo (registry-db)))"
Error: (error (void-variable bar))
 (foo #s(registry-db unbound nil 2305843009213693951 0.1 nil nil
#s(hash-table size 100 test eql rehash-size 2.0 rehash-threshold
0.8125 data ( ...)) #s(hash-table size 10000 test equal rehash-size
2.0 rehash-threshold 0.8125 data ( ...))))
 (let ((debug-on-error t)) (require 'registry) (defun foo (x) bar)
(foo (registry-db)))
 (eval (let ((debug-on-error t)) (require 'registry) (defun foo (x)
bar) (foo (registry-db))) t)
 (command-line-1 ("--eval" "(let ((debug-on-error t)) (require
'registry) (defun foo (x) bar) (foo (registry-db)))"))
 (command-line)
 (normal-top-level)

And now with a workaround that disables this "failsafe" mode:

$ emacs -Q --batch --eval "(advice-add 'terminal-name :override
(lambda () \"workaround\"))" --eval "(let ((debug-on-error t))
(require 'registry) (defun foo (x) bar) (foo (registry-db)))"
Debugger entered--Lisp error: (void-variable bar)
 foo(#<registry-db registry-db-1575c8f95a00>)
 (let ((debug-on-error t)) (require 'registry) (defun foo (x) bar)
(foo (registry-db)))
 eval((let ((debug-on-error t)) (require 'registry) (defun foo (x)
bar) (foo (registry-db))) t)
 command-line-1(("--eval" "(advice-add 'terminal-name :override
(lambda () \"w..." "--eval" "(let ((debug-on-error t)) (require
'registry) (def..."))
 command-line()
 normal-top-level()

Without the workaround, `debugger-print-function' (i.e. `cl-prin1') is
never called and in the second line of output you can see
"#s(registry-db ..."). With the workaround `cl-prin1' is called where
it should be, and you can see "#<registry-db ..." instead.

I'm not sure if the "failsafe" mode is meant to operate in batch mode
or not: I traced it down to the commit where it was added, but the
commit doesn't state the reason for the change. If "failsafe" is only
meant for when exceptions happen in normal mode before Emacs is
properly initialized, then adding "(not noninteractive)" to its
condition should be enough. If it is actually meant (also) for batch
mode, it should work more like the "normal" debugging backtrace
generating code, so that exceptions you see inside normal Emacs and
when printed from batch mode look the same.

Paul


On Sat, 21 Dec 2019 at 10:22, Eli Zaretskii <[hidden email]> wrote:

>
> > From: Paul Pogonyshev <[hidden email]>
> > Date: Mon, 16 Dec 2019 23:34:42 +0100
> >
> > +   ((and (eq t (framep (selected-frame)))
> > +         (equal "initial_terminal" (terminal-name)))
> > +    ;; We're in the initial-frame (where `message' just outputs to stdout) so
> > +    ;; there's no tty or GUI frame to display the backtrace and interact with
> > +    ;; it: just dump a backtrace to stdout.
> > +    ;; This happens for example while handling an error in code from
> > +    ;; early-init.el with --debug-init.
> > +    (message "Error: %S" args)
> > [...]
> >
> > The condition seems to always be true when `noninteractive' is t. Is
> > this intentional? It appears to mean that all debug/backtrace
> > customizations in batch mode are meaningless, since debugger just goes
> > the "failsafe" route and prints backtrace with simple `message' calls
> > now.
>
> Can you please elaborate about the debug/backtrace customizations you
> did, which are bypassed due to this code?  What are those
> customizations supposed to do?