diff options
| author | Stefan Monnier | 2023-12-25 22:40:02 -0500 |
|---|---|---|
| committer | Stefan Monnier | 2025-07-15 13:49:29 -0400 |
| commit | c3f3fe136cefc4c3aed960b175053e7c048aa979 (patch) | |
| tree | 0ed24837d09d9709f1bd43fba97d1d7bea14ca1a /src/eval.c | |
| parent | 4c9b37660771776563cf79bb3a2b6e692aa05ca2 (diff) | |
| download | emacs-c3f3fe136cefc4c3aed960b175053e7c048aa979.tar.gz emacs-c3f3fe136cefc4c3aed960b175053e7c048aa979.zip | |
Add `redisplay_counter` to catch nested redisplays and abort outer one
The redisplay code is not re-entrant. To allow running ELisp code
from within redisplay, we have some hacks (e.g. `inhibit-redisplay`)
that try to avoid the resulting breakage.
This commit adds another one of those hacks, which tries
to get closer to the core of the problem, thereby making it "safe"
to override `inhibit-redisplay`, e.g. to debug jit-lock code.
* src/dispextern.h (redisplay_counter): Declare.
* src/xdisp.c (redisplay_counter): Define.
(redisplay_internal) Increment it.
(dsafe__call): Use it, in case `inhibit-redisplay` is overridden.
* src/eval.c (call_debugger): Use it as well to refine the test
we already had.
Diffstat (limited to 'src/eval.c')
| -rw-r--r-- | src/eval.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/src/eval.c b/src/eval.c index 5e2b5bff796..204adb62472 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -302,6 +302,7 @@ call_debugger (Lisp_Object arg) | |||
| 302 | /* Resetting redisplaying_p to 0 makes sure that debug output is | 302 | /* Resetting redisplaying_p to 0 makes sure that debug output is |
| 303 | displayed if the debugger is invoked during redisplay. */ | 303 | displayed if the debugger is invoked during redisplay. */ |
| 304 | debug_while_redisplaying = redisplaying_p; | 304 | debug_while_redisplaying = redisplaying_p; |
| 305 | int redisplay_counter_before = redisplay_counter; | ||
| 305 | redisplaying_p = 0; | 306 | redisplaying_p = 0; |
| 306 | specbind (Qdebugger_may_continue, | 307 | specbind (Qdebugger_may_continue, |
| 307 | debug_while_redisplaying ? Qnil : Qt); | 308 | debug_while_redisplaying ? Qnil : Qt); |
| @@ -323,9 +324,10 @@ call_debugger (Lisp_Object arg) | |||
| 323 | /* Interrupting redisplay and resuming it later is not safe under | 324 | /* Interrupting redisplay and resuming it later is not safe under |
| 324 | all circumstances. So, when the debugger returns, abort the | 325 | all circumstances. So, when the debugger returns, abort the |
| 325 | interrupted redisplay by going back to the top-level. */ | 326 | interrupted redisplay by going back to the top-level. */ |
| 326 | /* FIXME: Move this to the redisplay code? */ | ||
| 327 | if (debug_while_redisplaying | 327 | if (debug_while_redisplaying |
| 328 | && !EQ (Vdebugger, Qdebug_early)) | 328 | && redisplay_counter_before != redisplay_counter) |
| 329 | /* FIXME: Rather than jump all the way to `top-level` | ||
| 330 | we should exit only the current redisplay. */ | ||
| 329 | Ftop_level (); | 331 | Ftop_level (); |
| 330 | 332 | ||
| 331 | return unbind_to (count, val); | 333 | return unbind_to (count, val); |