diff options
| author | Mattias EngdegÄrd | 2022-09-19 10:55:09 +0200 |
|---|---|---|
| committer | Mattias EngdegÄrd | 2022-09-19 19:30:03 +0200 |
| commit | 60102016e416e5c19fa5945aeb80693dac7ff2e6 (patch) | |
| tree | 69979ff773d7031634e7bc4f4388abc4ae104717 /src | |
| parent | a7c65fc6660878e244432a5b25fb3a4ff20e8604 (diff) | |
| download | emacs-60102016e416e5c19fa5945aeb80693dac7ff2e6.tar.gz emacs-60102016e416e5c19fa5945aeb80693dac7ff2e6.zip | |
Abolish max-specpdl-size (bug#57911)
The max-lisp-eval-depth limit is sufficient to prevent unbounded stack
growth including the specbind stack; simplify matters for the user by
not having them to worry about two different limits. This change
turns max-specpdl-size into a harmless variable with no effects,
to keep existing code happy.
* lisp/subr.el (max-specpdl-size):
Define as an ordinary (but obsolete) dynamic variable.
* admin/grammars/Makefile.in:
* doc/lispintro/emacs-lisp-intro.texi (Loops & Recursion):
* doc/lispref/control.texi (Cleanups):
* doc/lispref/edebug.texi (Checking Whether to Stop):
* doc/lispref/eval.texi (Eval):
* doc/lispref/variables.texi (Local Variables):
* doc/misc/calc.texi (Recursion Depth):
Update documentation.
* etc/NEWS: Announce.
* src/eval.c
(FletX): Use safe iteration to guard against circular bindings list.
(syms_of_eval): Remove old max-specpdl-size definition.
(init_eval_once, restore_stack_limits, call_debugger)
(signal_or_quit, grow_specpdl_allocation):
* leim/Makefile.in:
* lisp/Makefile.in:
* lisp/calc/calc-stuff.el (calc-more-recursion-depth)
(calc-less-recursion-depth):
* lisp/calc/calc.el (calc-do):
* lisp/cedet/semantic/ede-grammar.el (ede-proj-makefile-insert-rules):
* lisp/cedet/semantic/grammar.el (semantic-grammar-batch-build-one-package):
* lisp/cus-start.el (standard):
* lisp/emacs-lisp/comp.el (comp--native-compile):
* lisp/emacs-lisp/edebug.el (edebug-max-depth):
(edebug-read-and-maybe-wrap-form, edebug-default-enter):
* lisp/emacs-lisp/regexp-opt.el (regexp-opt):
* lisp/eshell/esh-mode.el (eshell-mode):
* lisp/loadup.el (max-specpdl-size):
* lisp/mh-e/mh-e.el (mh-invisible-headers):
* lisp/net/shr.el (shr-insert-document, shr-descend):
* lisp/play/hanoi.el (hanoi-internal):
* lisp/progmodes/cperl-mode.el:
* src/fileio.c (Fdo_auto_save):
Remove references to and modifications of max-specpdl-size.
Diffstat (limited to 'src')
| -rw-r--r-- | src/eval.c | 60 | ||||
| -rw-r--r-- | src/fileio.c | 5 |
2 files changed, 6 insertions, 59 deletions
diff --git a/src/eval.c b/src/eval.c index bd414fb8687..7da1d8fb989 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -211,9 +211,7 @@ backtrace_thread_next (struct thread_state *tstate, union specbinding *pdl) | |||
| 211 | void | 211 | void |
| 212 | init_eval_once (void) | 212 | init_eval_once (void) |
| 213 | { | 213 | { |
| 214 | /* Don't forget to update docs | 214 | /* Don't forget to update docs (lispref node "Eval"). */ |
| 215 | (lispref nodes "Local Variables" and "Eval"). */ | ||
| 216 | max_specpdl_size = 2500; | ||
| 217 | max_lisp_eval_depth = 1600; | 215 | max_lisp_eval_depth = 1600; |
| 218 | Vrun_hooks = Qnil; | 216 | Vrun_hooks = Qnil; |
| 219 | pdumper_do_now_and_after_load (init_eval_once_for_pdumper); | 217 | pdumper_do_now_and_after_load (init_eval_once_for_pdumper); |
| @@ -265,8 +263,7 @@ max_ensure_room (intmax_t *m, intmax_t a, intmax_t b) | |||
| 265 | static void | 263 | static void |
| 266 | restore_stack_limits (Lisp_Object data) | 264 | restore_stack_limits (Lisp_Object data) |
| 267 | { | 265 | { |
| 268 | integer_to_intmax (XCAR (data), &max_specpdl_size); | 266 | integer_to_intmax (data, &max_lisp_eval_depth); |
| 269 | integer_to_intmax (XCDR (data), &max_lisp_eval_depth); | ||
| 270 | } | 267 | } |
| 271 | 268 | ||
| 272 | /* Call the Lisp debugger, giving it argument ARG. */ | 269 | /* Call the Lisp debugger, giving it argument ARG. */ |
| @@ -278,9 +275,6 @@ call_debugger (Lisp_Object arg) | |||
| 278 | specpdl_ref count = SPECPDL_INDEX (); | 275 | specpdl_ref count = SPECPDL_INDEX (); |
| 279 | Lisp_Object val; | 276 | Lisp_Object val; |
| 280 | intmax_t old_depth = max_lisp_eval_depth; | 277 | intmax_t old_depth = max_lisp_eval_depth; |
| 281 | /* Do not allow max_specpdl_size less than actual depth (Bug#16603). */ | ||
| 282 | ptrdiff_t counti = specpdl_ref_to_count (count); | ||
| 283 | intmax_t old_max = max (max_specpdl_size, counti); | ||
| 284 | 278 | ||
| 285 | /* The previous value of 40 is too small now that the debugger | 279 | /* The previous value of 40 is too small now that the debugger |
| 286 | prints using cl-prin1 instead of prin1. Printing lists nested 8 | 280 | prints using cl-prin1 instead of prin1. Printing lists nested 8 |
| @@ -288,20 +282,8 @@ call_debugger (Lisp_Object arg) | |||
| 288 | currently requires 77 additional frames. See bug#31919. */ | 282 | currently requires 77 additional frames. See bug#31919. */ |
| 289 | max_ensure_room (&max_lisp_eval_depth, lisp_eval_depth, 100); | 283 | max_ensure_room (&max_lisp_eval_depth, lisp_eval_depth, 100); |
| 290 | 284 | ||
| 291 | /* While debugging Bug#16603, previous value of 100 was found | ||
| 292 | too small to avoid specpdl overflow in the debugger itself. */ | ||
| 293 | max_ensure_room (&max_specpdl_size, counti, 200); | ||
| 294 | |||
| 295 | if (old_max == counti) | ||
| 296 | { | ||
| 297 | /* We can enter the debugger due to specpdl overflow (Bug#16603). */ | ||
| 298 | specpdl_ptr--; | ||
| 299 | grow_specpdl (); | ||
| 300 | } | ||
| 301 | |||
| 302 | /* Restore limits after leaving the debugger. */ | 285 | /* Restore limits after leaving the debugger. */ |
| 303 | record_unwind_protect (restore_stack_limits, | 286 | record_unwind_protect (restore_stack_limits, make_int (old_depth)); |
| 304 | Fcons (make_int (old_max), make_int (old_depth))); | ||
| 305 | 287 | ||
| 306 | #ifdef HAVE_WINDOW_SYSTEM | 288 | #ifdef HAVE_WINDOW_SYSTEM |
| 307 | if (display_hourglass_p) | 289 | if (display_hourglass_p) |
| @@ -933,12 +915,9 @@ usage: (let* VARLIST BODY...) */) | |||
| 933 | lexenv = Vinternal_interpreter_environment; | 915 | lexenv = Vinternal_interpreter_environment; |
| 934 | 916 | ||
| 935 | Lisp_Object varlist = XCAR (args); | 917 | Lisp_Object varlist = XCAR (args); |
| 936 | while (CONSP (varlist)) | 918 | FOR_EACH_TAIL (varlist) |
| 937 | { | 919 | { |
| 938 | maybe_quit (); | ||
| 939 | |||
| 940 | elt = XCAR (varlist); | 920 | elt = XCAR (varlist); |
| 941 | varlist = XCDR (varlist); | ||
| 942 | if (SYMBOLP (elt)) | 921 | if (SYMBOLP (elt)) |
| 943 | { | 922 | { |
| 944 | var = elt; | 923 | var = elt; |
| @@ -1752,8 +1731,6 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit) | |||
| 1752 | { | 1731 | { |
| 1753 | /* Edebug takes care of restoring these variables when it exits. */ | 1732 | /* Edebug takes care of restoring these variables when it exits. */ |
| 1754 | max_ensure_room (&max_lisp_eval_depth, lisp_eval_depth, 20); | 1733 | max_ensure_room (&max_lisp_eval_depth, lisp_eval_depth, 20); |
| 1755 | ptrdiff_t counti = specpdl_ref_to_count (SPECPDL_INDEX ()); | ||
| 1756 | max_ensure_room (&max_specpdl_size, counti, 40); | ||
| 1757 | 1734 | ||
| 1758 | call2 (Vsignal_hook_function, error_symbol, data); | 1735 | call2 (Vsignal_hook_function, error_symbol, data); |
| 1759 | } | 1736 | } |
| @@ -1822,8 +1799,6 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit) | |||
| 1822 | { | 1799 | { |
| 1823 | max_ensure_room (&max_lisp_eval_depth, lisp_eval_depth, 100); | 1800 | max_ensure_room (&max_lisp_eval_depth, lisp_eval_depth, 100); |
| 1824 | specpdl_ref count = SPECPDL_INDEX (); | 1801 | specpdl_ref count = SPECPDL_INDEX (); |
| 1825 | ptrdiff_t counti = specpdl_ref_to_count (count); | ||
| 1826 | max_ensure_room (&max_specpdl_size, counti, 200); | ||
| 1827 | specbind (Qdebugger, Qdebug_early); | 1802 | specbind (Qdebugger, Qdebug_early); |
| 1828 | call_debugger (list2 (Qerror, Fcons (error_symbol, data))); | 1803 | call_debugger (list2 (Qerror, Fcons (error_symbol, data))); |
| 1829 | unbind_to (count, Qnil); | 1804 | unbind_to (count, Qnil); |
| @@ -1839,12 +1814,10 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit) | |||
| 1839 | { | 1814 | { |
| 1840 | max_ensure_room (&max_lisp_eval_depth, lisp_eval_depth, 100); | 1815 | max_ensure_room (&max_lisp_eval_depth, lisp_eval_depth, 100); |
| 1841 | specpdl_ref count = SPECPDL_INDEX (); | 1816 | specpdl_ref count = SPECPDL_INDEX (); |
| 1842 | ptrdiff_t counti = specpdl_ref_to_count (count); | ||
| 1843 | AUTO_STRING (redisplay_trace, "*Redisplay_trace*"); | 1817 | AUTO_STRING (redisplay_trace, "*Redisplay_trace*"); |
| 1844 | Lisp_Object redisplay_trace_buffer; | 1818 | Lisp_Object redisplay_trace_buffer; |
| 1845 | AUTO_STRING (gap, "\n\n\n\n"); /* Separates things in *Redisplay-trace* */ | 1819 | AUTO_STRING (gap, "\n\n\n\n"); /* Separates things in *Redisplay-trace* */ |
| 1846 | Lisp_Object delayed_warning; | 1820 | Lisp_Object delayed_warning; |
| 1847 | max_ensure_room (&max_specpdl_size, counti, 200); | ||
| 1848 | redisplay_trace_buffer = Fget_buffer_create (redisplay_trace, Qnil); | 1821 | redisplay_trace_buffer = Fget_buffer_create (redisplay_trace, Qnil); |
| 1849 | current_buffer = XBUFFER (redisplay_trace_buffer); | 1822 | current_buffer = XBUFFER (redisplay_trace_buffer); |
| 1850 | if (!backtrace_yet) /* Are we on the first backtrace of the command? */ | 1823 | if (!backtrace_yet) /* Are we on the first backtrace of the command? */ |
| @@ -2376,17 +2349,12 @@ grow_specpdl_allocation (void) | |||
| 2376 | eassert (specpdl_ptr == specpdl_end); | 2349 | eassert (specpdl_ptr == specpdl_end); |
| 2377 | 2350 | ||
| 2378 | specpdl_ref count = SPECPDL_INDEX (); | 2351 | specpdl_ref count = SPECPDL_INDEX (); |
| 2379 | ptrdiff_t max_size = min (max_specpdl_size, PTRDIFF_MAX - 1000); | 2352 | ptrdiff_t max_size = PTRDIFF_MAX - 1000; |
| 2380 | union specbinding *pdlvec = specpdl - 1; | 2353 | union specbinding *pdlvec = specpdl - 1; |
| 2381 | ptrdiff_t size = specpdl_end - specpdl; | 2354 | ptrdiff_t size = specpdl_end - specpdl; |
| 2382 | ptrdiff_t pdlvecsize = size + 1; | 2355 | ptrdiff_t pdlvecsize = size + 1; |
| 2383 | if (max_size <= size) | 2356 | if (max_size <= size) |
| 2384 | { | 2357 | xsignal0 (Qexcessive_variable_binding); /* Can't happen, essentially. */ |
| 2385 | if (max_specpdl_size < 400) | ||
| 2386 | max_size = max_specpdl_size = 400; | ||
| 2387 | if (max_size <= size) | ||
| 2388 | xsignal0 (Qexcessive_variable_binding); | ||
| 2389 | } | ||
| 2390 | pdlvec = xpalloc (pdlvec, &pdlvecsize, 1, max_size + 1, sizeof *specpdl); | 2358 | pdlvec = xpalloc (pdlvec, &pdlvecsize, 1, max_size + 1, sizeof *specpdl); |
| 2391 | specpdl = pdlvec + 1; | 2359 | specpdl = pdlvec + 1; |
| 2392 | specpdl_end = specpdl + pdlvecsize - 1; | 2360 | specpdl_end = specpdl + pdlvecsize - 1; |
| @@ -4229,22 +4197,6 @@ Lisp_Object backtrace_top_function (void) | |||
| 4229 | void | 4197 | void |
| 4230 | syms_of_eval (void) | 4198 | syms_of_eval (void) |
| 4231 | { | 4199 | { |
| 4232 | DEFVAR_INT ("max-specpdl-size", max_specpdl_size, | ||
| 4233 | doc: /* Limit on number of Lisp variable bindings and `unwind-protect's. | ||
| 4234 | |||
| 4235 | If Lisp code tries to use more bindings than this amount, an error is | ||
| 4236 | signaled. | ||
| 4237 | |||
| 4238 | You can safely increase this variable substantially if the default | ||
| 4239 | value proves inconveniently small. However, if you increase it too | ||
| 4240 | much, Emacs could run out of memory trying to make the stack bigger. | ||
| 4241 | Note that this limit may be silently increased by the debugger if | ||
| 4242 | `debug-on-error' or `debug-on-quit' is set. | ||
| 4243 | |||
| 4244 | \"spec\" is short for \"special variables\", i.e., dynamically bound | ||
| 4245 | variables. \"PDL\" is short for \"push-down list\", which is an old | ||
| 4246 | term for \"stack\". */); | ||
| 4247 | |||
| 4248 | DEFVAR_INT ("max-lisp-eval-depth", max_lisp_eval_depth, | 4200 | DEFVAR_INT ("max-lisp-eval-depth", max_lisp_eval_depth, |
| 4249 | doc: /* Limit on depth in `eval', `apply' and `funcall' before error. | 4201 | doc: /* Limit on depth in `eval', `apply' and `funcall' before error. |
| 4250 | 4202 | ||
diff --git a/src/fileio.c b/src/fileio.c index 6efea8ac369..dd7f85ec97f 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -6019,11 +6019,6 @@ A non-nil CURRENT-ONLY argument means save only current buffer. */) | |||
| 6019 | bool old_message_p = 0; | 6019 | bool old_message_p = 0; |
| 6020 | struct auto_save_unwind auto_save_unwind; | 6020 | struct auto_save_unwind auto_save_unwind; |
| 6021 | 6021 | ||
| 6022 | intmax_t sum = INT_ADD_WRAPV (specpdl_end - specpdl, 40, &sum) | ||
| 6023 | ? INTMAX_MAX : sum; | ||
| 6024 | if (max_specpdl_size < sum) | ||
| 6025 | max_specpdl_size = sum; | ||
| 6026 | |||
| 6027 | if (minibuf_level) | 6022 | if (minibuf_level) |
| 6028 | no_message = Qt; | 6023 | no_message = Qt; |
| 6029 | 6024 | ||