From: Alan Mackenzie <acm@muc.de>
To: Eli Zaretskii <eliz@gnu.org>
Cc: larsi@gnus.org, emacs-devel@gnu.org
Subject: Fontification error backtrace [Was: Why is it so difficult to get a Lisp backtrace?]
Date: Mon, 27 Jun 2022 19:48:45 +0000 [thread overview]
Message-ID: <YroJnaBT4RR2SZ9t@ACM> (raw)
In-Reply-To: <83o7yg9f0w.fsf@gnu.org>
Hello, Eli.
On Sun, Jun 26, 2022 at 08:20:47 +0300, Eli Zaretskii wrote:
> > Date: Sat, 25 Jun 2022 19:45:49 +0000
> > Cc: larsi@gnus.org, emacs-devel@gnu.org
> > From: Alan Mackenzie <acm@muc.de>
> > > The only two ways of having that, AFAIK, are:
> > > . emit the backtrace int *Messages*
> > > . add the backtrace to delayed-warnings-list
> > Why can't the backtrace be generated and stored, and only displayed at a
> > subsequent redisplay (probably the next one)?
> That's what the second alternative above already does.
OK, I've got some code. :-)
What it does, on a fontification error during redisplay, is to write a
backtrace into the *Backtrace* buffer, attempts a pop-to-buffer (which
isn't working, not surprisingly), and aborts the redisplay.
The basic idea is to note the condition-case handler which is scheduled
to handle any fontification error. In signal_or_quit, if that is the
handler which is about to handle an error, generate a backtrace instead.
To try it out, set the new variable backtrace-on-fontification-error to
non-nil, and tweak some code to generate an error during fontification.
As already noted, the *Backtrace* buffer doesn't appear on the screen,
yet. Any hints on how to achieve this would be most welcome. It seems I
could really do with after-redisplay-hook, in which I could call
pop-to-buffer, then cause redisplay to be restarted.
Maybe this code could go into Emacs 29, once it's working properly.
diff --git a/src/dispextern.h b/src/dispextern.h
index c7399ca299..4bf6fb843f 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -3406,6 +3406,7 @@ void move_it_in_display_line (struct it *it,
int partial_line_height (struct it *it_origin);
bool in_display_vector_p (struct it *);
int frame_mode_line_height (struct frame *);
+extern struct handler *redisplay_deep_handler;
extern bool redisplaying_p;
extern bool help_echo_showing_p;
extern Lisp_Object help_echo_string, help_echo_window;
diff --git a/src/eval.c b/src/eval.c
index 346dff8bdc..ad5eb9dc7e 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1550,9 +1550,12 @@ internal_condition_case_n (Lisp_Object (*bfun) (ptrdiff_t, Lisp_Object *),
Lisp_Object handlers,
Lisp_Object (*hfun) (Lisp_Object err,
ptrdiff_t nargs,
- Lisp_Object *args))
+ Lisp_Object *args),
+ struct handler **handler)
{
struct handler *c = push_handler (handlers, CONDITION_CASE);
+ if (handler)
+ *handler = c;
if (sys_setjmp (c->jmp))
{
Lisp_Object val = handlerlist->val;
@@ -1812,6 +1815,32 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit)
unbind_to (count, Qnil);
}
+ /* If an error is signalled during fontification in redisplay, print
+ a backtrace into the buffer *Backtrace*. */
+ if (!debugger_called && !NILP (error_symbol)
+ && redisplay_fontifying
+ && backtrace_on_fontification_error
+ && (NILP (clause) || h == redisplay_deep_handler)
+ && NILP (Vinhibit_debugger)
+ && !NILP (Ffboundp (Qdebug_early)))
+ {
+ max_ensure_room (&max_lisp_eval_depth, lisp_eval_depth, 100);
+ specpdl_ref count = SPECPDL_INDEX ();
+ ptrdiff_t counti = specpdl_ref_to_count (count);
+ Lisp_Object backtrace_buffer;
+ max_ensure_room (&max_specpdl_size, counti, 200);
+ backtrace_buffer = Fget_buffer_create (make_string ("*Backtrace*", 11),
+ Qnil);
+ current_buffer = XBUFFER (backtrace_buffer);
+ Ferase_buffer ();
+ specbind (Qstandard_output, backtrace_buffer);
+ specbind (Qdebugger, Qdebug_early);
+ call_debugger (list2 (Qerror, Fcons (error_symbol, data)));
+ unbind_to (count, Qnil);
+ call1 (intern ("pop-to-buffer"), backtrace_buffer);
+ Fthrow (Qtop_level, Qt); /* This might not be needed. */
+ }
+
if (!NILP (clause))
{
Lisp_Object unwind_data
@@ -4269,6 +4298,12 @@ Does not apply if quit is handled by a `condition-case'. */);
DEFVAR_BOOL ("debug-on-next-call", debug_on_next_call,
doc: /* Non-nil means enter debugger before next `eval', `apply' or `funcall'. */);
+ DEFVAR_BOOL ("backtrace-on-fontification-error", backtrace_on_fontification_error,
+ doc: /* Non-nil means show a backtrace if a fontification error occurs in redisplay.
+When this happens, it causes the current redisplay to be aborted and a new one
+including the *Backtrace* buffer to be performed. */);
+ backtrace_on_fontification_error = false;
+
DEFVAR_BOOL ("debugger-may-continue", debugger_may_continue,
doc: /* Non-nil means debugger may continue execution.
This is nil when the debugger is called under circumstances where it
diff --git a/src/keyboard.c b/src/keyboard.c
index e62b2e56d3..fdce343d6f 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -1878,7 +1878,7 @@ safe_run_hook_funcall (ptrdiff_t nargs, Lisp_Object *args)
/* Yes, run_hook_with_args works with args in the other order. */
internal_condition_case_n (safe_run_hooks_1,
2, ((Lisp_Object []) {args[1], args[0]}),
- Qt, safe_run_hooks_error);
+ Qt, safe_run_hooks_error, NULL);
return Qnil;
}
diff --git a/src/lisp.h b/src/lisp.h
index 05b0754ff6..16830c7d8e 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4558,7 +4558,7 @@ extern Lisp_Object internal_condition_case_1 (Lisp_Object (*) (Lisp_Object), Lis
extern Lisp_Object internal_condition_case_2 (Lisp_Object (*) (Lisp_Object, Lisp_Object), Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object (*) (Lisp_Object));
extern Lisp_Object internal_condition_case_n
(Lisp_Object (*) (ptrdiff_t, Lisp_Object *), ptrdiff_t, Lisp_Object *,
- Lisp_Object, Lisp_Object (*) (Lisp_Object, ptrdiff_t, Lisp_Object *));
+ Lisp_Object, Lisp_Object (*) (Lisp_Object, ptrdiff_t, Lisp_Object *), struct handler **);
extern Lisp_Object internal_catch_all (Lisp_Object (*) (void *), void *, Lisp_Object (*) (enum nonlocal_exit, Lisp_Object));
extern struct handler *push_handler (Lisp_Object, enum handlertype)
ATTRIBUTE_RETURNS_NONNULL;
diff --git a/src/xdisp.c b/src/xdisp.c
index 90809ac3ab..6b2d09efb2 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -615,6 +615,9 @@ fill_column_indicator_column (struct it *it, int char_width)
bool noninteractive_need_newline;
+/* The handler structure which will catch errors in fontification code. */
+struct handler *redisplay_deep_handler;
+
/* True means print newline to message log before next message. */
static bool message_log_need_newline;
@@ -3013,7 +3016,8 @@ safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap)
/* Use Qt to ensure debugger does not run,
so there is no possibility of wanting to redisplay. */
val = internal_condition_case_n (Ffuncall, nargs, args, Qt,
- safe_eval_handler);
+ safe_eval_handler,
+ &redisplay_deep_handler);
val = SAFE_FREE_UNBIND_TO (count, val);
}
@@ -4320,6 +4324,7 @@ handle_fontified_prop (struct it *it)
val = Vfontification_functions;
specbind (Qfontification_functions, Qnil);
+ specbind (Qredisplay_fontifying, Qt);
eassert (it->end_charpos == ZV);
@@ -26431,7 +26436,7 @@ display_mode_element (struct it *it, int depth, int field_width, int precision,
Flength (elt),
props,
elt}),
- Qt, safe_eval_handler);
+ Qt, safe_eval_handler, NULL);
/* Add this item to mode_line_proptrans_alist. */
mode_line_proptrans_alist
= Fcons (Fcons (elt, props),
@@ -35704,6 +35709,7 @@ be let-bound around code that needs to disable messages temporarily. */);
DEFSYM (QCfile, ":file");
DEFSYM (Qfontified, "fontified");
DEFSYM (Qfontification_functions, "fontification-functions");
+ DEFSYM (Qredisplay_fontifying, "redisplay-fontifying");
/* Name of the symbol which disables Lisp evaluation in 'display'
properties. This is used by enriched.el. */
@@ -36221,6 +36227,10 @@ fontified regions the property `fontified'. */);
Vfontification_functions = Qnil;
Fmake_variable_buffer_local (Qfontification_functions);
+ DEFVAR_BOOL ("redisplay-fontifying", redisplay_fontifying,
+ doc: /* Non-nil when fontification invoked from redisplay is in progress. */);
+ redisplay_fontifying = false;
+
DEFVAR_BOOL ("unibyte-display-via-language-environment",
unibyte_display_via_language_environment,
doc: /* Non-nil means display unibyte text according to language environment.
diff --git a/src/xfns.c b/src/xfns.c
index 1372809da6..dc18cfb4ae 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -3405,7 +3405,7 @@ x_xim_text_to_utf8_unix (XIMText *text, ptrdiff_t *length)
waiting_for_input = false;
arg = make_mint_ptr (&data);
internal_condition_case_n (x_xim_text_to_utf8_unix_1, 1, &arg,
- Qt, x_xim_text_to_utf8_unix_2);
+ Qt, x_xim_text_to_utf8_unix_2, NULL);
waiting_for_input = was_waiting_for_input_p;
*length = coding.produced;
--
Alan Mackenzie (Nuremberg, Germany).
next prev parent reply other threads:[~2022-06-27 19:48 UTC|newest]
Thread overview: 54+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-06-25 13:42 Why is it so difficult to get a Lisp backtrace? Alan Mackenzie
2022-06-25 15:26 ` Alan Mackenzie
2022-06-25 15:30 ` Stefan Kangas
2022-06-25 15:52 ` Alan Mackenzie
2022-06-25 16:27 ` Stefan Kangas
2022-06-25 15:35 ` Lars Ingebrigtsen
2022-06-25 15:59 ` Alan Mackenzie
2022-06-25 16:51 ` Eli Zaretskii
2022-06-25 19:45 ` Alan Mackenzie
2022-06-26 5:20 ` Eli Zaretskii
2022-06-27 19:48 ` Alan Mackenzie [this message]
2022-06-28 11:43 ` Fontification error backtrace [Was: Why is it so difficult to get a Lisp backtrace?] Lars Ingebrigtsen
2022-06-28 11:57 ` Eli Zaretskii
2022-06-28 17:28 ` Alan Mackenzie
2022-06-28 18:17 ` Eli Zaretskii
2022-06-28 19:31 ` Alan Mackenzie
2022-06-29 19:00 ` Eli Zaretskii
2022-07-12 19:48 ` Redisplay hook error bactraces [Was: Fontification error backtrace] Alan Mackenzie
2022-07-13 12:33 ` Eli Zaretskii
2022-07-13 18:41 ` Redisplay hook error backtraces Alan Mackenzie
2022-07-13 19:00 ` Eli Zaretskii
2022-07-13 20:12 ` Alan Mackenzie
2022-07-13 20:49 ` Stefan Monnier
2022-07-14 5:12 ` Eli Zaretskii
2022-07-14 9:01 ` Alan Mackenzie
2022-07-14 9:10 ` Eli Zaretskii
2022-07-14 13:42 ` Alan Mackenzie
2022-07-14 13:59 ` Eli Zaretskii
2022-07-14 16:07 ` Alan Mackenzie
2022-07-14 16:18 ` Stefan Monnier
2022-07-14 19:47 ` Alan Mackenzie
2022-07-14 20:48 ` Stefan Monnier
2022-07-15 5:50 ` Eli Zaretskii
2022-07-15 18:18 ` Alan Mackenzie
2022-07-16 6:03 ` Eli Zaretskii
2022-07-14 17:09 ` Eli Zaretskii
2022-07-14 19:33 ` Alan Mackenzie
2022-07-16 6:12 ` Eli Zaretskii
2022-07-16 15:45 ` Alan Mackenzie
2022-07-13 19:13 ` Redisplay hook error bactraces [Was: Fontification error backtrace] Stefan Monnier
2022-07-13 19:24 ` Eli Zaretskii
2022-07-13 19:58 ` Alan Mackenzie
2022-07-13 20:45 ` Stefan Monnier
2022-06-30 20:34 ` Fontification error backtrace [Was: Why is it so difficult to get a Lisp backtrace?] Stefan Monnier
2022-07-01 5:39 ` Eli Zaretskii
2022-07-01 15:34 ` Juri Linkov
2022-07-01 16:04 ` Eli Zaretskii
2022-07-01 19:14 ` Juri Linkov
2022-07-01 19:26 ` Stefan Monnier
2022-07-02 5:53 ` Eli Zaretskii
2022-07-02 21:15 ` Stefan Monnier
2022-07-02 20:27 ` Alan Mackenzie
2022-07-02 21:12 ` Stefan Monnier
2022-06-26 8:45 ` Why is it so difficult to get a Lisp backtrace? Stefan Monnier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=YroJnaBT4RR2SZ9t@ACM \
--to=acm@muc.de \
--cc=eliz@gnu.org \
--cc=emacs-devel@gnu.org \
--cc=larsi@gnus.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.