* bug#5662: flet not undone on lisp nesting error @ 2010-03-01 2:30 Dan Davison 2010-03-05 20:30 ` Stefan Monnier 2016-06-02 1:15 ` Noam Postavsky 0 siblings, 2 replies; 5+ messages in thread From: Dan Davison @ 2010-03-01 2:30 UTC (permalink / raw) To: 5662 If I trigger a lisp nesting error with an infinite recursion inside a let and an flet binding, then the effects of the flet are not undone, resulting in a change of binding at the top-level. (defun g () 'g-orig) (setq a 'a-orig) (defun h () (let ((a 'a-new)) (flet ((g () 'g-new)) (h)))) (h) ;; <-- Lisp nesting exceeds `max-lisp-eval-depth' (g) ;; g-new ! a ;; a-orig Dan If Emacs crashed, and you have the Emacs process in the gdb debugger, please include the output from the following gdb commands: `bt full' and `xbacktrace'. If you would like to further debug the crash, please read the file /usr/share/emacs/23.1/etc/DEBUG for instructions. In GNU Emacs 23.1.1 (i486-pc-linux-gnu, GTK+ Version 2.18.3) of 2009-11-10 on vernadsky, modified by Debian Windowing system distributor `The X.Org Foundation', version 11.0.10604000 configured using `configure '--build=i486-linux-gnu' '--host=i486-linux-gnu' '--prefix=/usr' '--sharedstatedir=/var/lib' '--libexecdir=/usr/lib' '--localstatedir=/var/lib' '--infodir=/usr/share/info' '--mandir=/usr/share/man' '--with-pop=yes' '--enable-locallisppath=/etc/emacs23:/etc/emacs:/usr/local/share/emacs/23.1/site-lisp:/usr/local/share/emacs/site-lisp:/usr/share/emacs/23.1/site-lisp:/usr/share/emacs/site-lisp:/usr/share/emacs/23.1/leim' '--with-x=yes' '--with-x-toolkit=gtk' '--with-toolkit-scroll-bars' 'build_alias=i486-linux-gnu' 'host_alias=i486-linux-gnu' 'CFLAGS=-DDEBIAN -g -O2' 'LDFLAGS=-g' 'CPPFLAGS='' Important settings: value of $LC_ALL: nil value of $LC_COLLATE: nil value of $LC_CTYPE: nil value of $LC_MESSAGES: nil value of $LC_MONETARY: nil value of $LC_NUMERIC: nil value of $LC_TIME: nil value of $LANG: en_GB.UTF-8 value of $XMODIFIERS: nil locale-coding-system: utf-8-unix default-enable-multibyte-characters: t Major mode: Article Minor modes in effect: erc-list-mode: t erc-menu-mode: t erc-autojoin-mode: t erc-ring-mode: t erc-networks-mode: t erc-pcomplete-mode: t erc-track-mode: t erc-track-minor-mode: t erc-match-mode: t erc-button-mode: t erc-fill-mode: t erc-stamp-mode: t erc-netsplit-mode: t erc-irccontrols-mode: t erc-noncommands-mode: t erc-move-to-prompt-mode: t erc-readonly-mode: t show-paren-mode: t recentf-mode: t yas/minor-mode: t diff-auto-refine-mode: t shell-dirtrack-mode: t tooltip-mode: t mouse-wheel-mode: t file-name-shadow-mode: t global-font-lock-mode: t font-lock-mode: t global-auto-composition-mode: t auto-composition-mode: t auto-encryption-mode: t auto-compression-mode: t line-number-mode: t transient-mark-mode: t Recent input: <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <tab> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <tab> C-x C-s <up> <up> <f1> <up> M-g <return> 1 0 0 <return> <down> <down> <down> <return> <down> <return> <escape> SPC SPC <up> <down> <prior> <prior> <escape> <up> <return> <escape> <escape> <down> <return> <escape> <next> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <up> <up> <up> <prior> <prior> <next> <next> <escape> <down> <down> <f10> <down> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <next> <prior> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <down> <down> <down> <down> <down> <down> <down> <down> <down> <up> <up> <up> <up> <up> <up> <down> <return> <escape> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <prior> <prior> <down> <down> <escape> <escape> <next> <up> <escape> <escape> <next> <prior> <prior> <escape> <up> <down> q <return> 2 0 0 <return> C-s f l e t C-s C-s <down> <up> <up> <return> <escape> <down> C-SPC M-> M-w M-x r e p o r t <tab> b u <tab> <return> Recent messages: End of message nnimap: Setting marks in INBOX...done No more unread newsgroups Retrieving newsgroup: INBOX... nnimap: Updating info for INBOX...done Fetching headers for INBOX...done Generating summary...done Mark saved where search started Mark set Saved text from "If I trigger a lisp nesting error with a" ^ permalink raw reply [flat|nested] 5+ messages in thread
* bug#5662: flet not undone on lisp nesting error 2010-03-01 2:30 bug#5662: flet not undone on lisp nesting error Dan Davison @ 2010-03-05 20:30 ` Stefan Monnier 2014-11-11 2:16 ` Jinseop Kim 2016-06-02 1:15 ` Noam Postavsky 1 sibling, 1 reply; 5+ messages in thread From: Stefan Monnier @ 2010-03-05 20:30 UTC (permalink / raw) To: Dan Davison; +Cc: 5662 > If I trigger a lisp nesting error with an infinite recursion inside a > let and an flet binding, then the effects of the flet are not undone, > resulting in a change of binding at the top-level. > (defun g () 'g-orig) > (setq a 'a-orig) > (defun h () > (let ((a 'a-new)) > (flet ((g () 'g-new)) > (h)))) > (h) ;; <-- Lisp nesting exceeds `max-lisp-eval-depth' > (g) ;; g-new ! > a ;; a-orig I can indeed reproduce it. I'm not sure yet what's going on, but it might be due to the "Lisp nesting exceeds `max-lisp-eval-depth'" error happening in the unwind-protect code (i.e. while undoing the `g' binding). The explanation can't be quite so simple, but my gut feeling tells me it's got to do with it. Stefan ^ permalink raw reply [flat|nested] 5+ messages in thread
* bug#5662: flet not undone on lisp nesting error 2010-03-05 20:30 ` Stefan Monnier @ 2014-11-11 2:16 ` Jinseop Kim 2014-11-11 15:50 ` Stefan Monnier 0 siblings, 1 reply; 5+ messages in thread From: Jinseop Kim @ 2014-11-11 2:16 UTC (permalink / raw) To: 5662; +Cc: Dan Davison You can see the bug of 'unwind-protect' using the following code. We must see the message “finally”, but are not output. ```elisp (defun endless-recursive () (endless-recursive)) (unwind-protect (endless-recursive) ;; body (message "finally”)) ;; unwind-forms ``` The `unwind-protect’ will call the `eval_sub’ function. And, the `eval_sub’ function check whether the infinite recursion as following code. ```c /* ./src/eval.c:2086: */ if (++lisp_eval_depth > max_lisp_eval_depth) { if (max_lisp_eval_depth < 100) max_lisp_eval_depth = 100; if (lisp_eval_depth > max_lisp_eval_depth) error ("Lisp nesting exceeds `max-lisp-eval-depth'"); } ``` The cause of problem is that `unwind-forms’ will call the `eval_sub’ function. Of course, the `eval_sub’ function check for infinite recursion. Consequently, the `unwind-protect’ wouldn't evaluate. You must be noted step 7~10. Problem's steps: 1. eval.c:1208:Funwind_protect: record_unwind_protect (unwind_body, XCDR (args)); 2. eval.c:1209:Funwind_protect: val = eval_sub (XCAR (args)); 3. eval.c:2090:eval_sub: if (lisp_eval_depth > max_lisp_eval_depth) error ("Lisp nesting exceeds `max-lisp-eval-depth'”); 4. eval.c:1582:xsignal: Fsignal (error_symbol, data); 5. eval.c:1558:Fsignal: unwind_to_catch (h, unwind_data); 6. eval.c:1161:unwind_to_catch: unbind_to (handlerlist->pdlcount, Qnil); 7. eval.c:3305:unbind_to: unwind_body // specpdl_ptr->unwind_ptr.func (specpdl_ptr->unwind_ptr.arg); 8. eval.c:476:unwind_body: Fprogn (body); 9. eval.c:462:Fprogn: val = eval_sub (XCAR (body)); 10. eval.c:2090:eval_sub: if (lisp_eval_depth > max_lisp_eval_depth) error ("Lisp nesting exceeds `max-lisp-eval-depth’”) You can avoid this problem using `ignore-errors’ macro. (eval.c:1175:unwind_to_catch: lisp_eval_depth = catch->lisp_eval_depth;) ```elisp (defun endless-recursive () (endless-recursive)) (unwind-protect (ignore-errors (endless-recursive)) (message "finally")) ``` > On Mar 6, 2010, at 5:30 AM, Stefan Monnier <monnier@iro.umontreal.ca> wrote: > >> If I trigger a lisp nesting error with an infinite recursion inside a >> let and an flet binding, then the effects of the flet are not undone, >> resulting in a change of binding at the top-level. > >> (defun g () 'g-orig) >> (setq a 'a-orig) > >> (defun h () >> (let ((a 'a-new)) >> (flet ((g () 'g-new)) >> (h)))) >> (h) ;; <-- Lisp nesting exceeds `max-lisp-eval-depth' >> (g) ;; g-new ! >> a ;; a-orig > > I can indeed reproduce it. I'm not sure yet what's going on, but it > might be due to the "Lisp nesting exceeds `max-lisp-eval-depth'" error > happening in the unwind-protect code (i.e. while undoing the `g' > binding). The explanation can't be quite so simple, but my gut feeling > tells me it's got to do with it. > > > Stefan > > > > ^ permalink raw reply [flat|nested] 5+ messages in thread
* bug#5662: flet not undone on lisp nesting error 2014-11-11 2:16 ` Jinseop Kim @ 2014-11-11 15:50 ` Stefan Monnier 0 siblings, 0 replies; 5+ messages in thread From: Stefan Monnier @ 2014-11-11 15:50 UTC (permalink / raw) To: Jinseop Kim; +Cc: Dan Davison, 5662 > The cause of problem is that `unwind-forms’ will call the `eval_sub’ > function. Of course, the `eval_sub’ function check for infinite > recursion. Consequently, the `unwind-protect’ wouldn't evaluate. Thanks for digging into it. Indeed, I think I see it now: in `unbind_to' we run the unwind_forms without updating lisp_eval_depth, so they're run with the lisp_eval_depth of the place where the signal was thrown, so if the signal was thrown because lisp_eval_depth > max_lisp_eval_depth, then the unwind forms will all fail by signaling error ("Lisp nesting exceeds `max-lisp-eval-depth'"). This said, at the time we run those unwind forms, the C stack is still at the same "very deep" state as when the error was signaled, so the lisp_eval_depth value is not completely wrong (more specifically, it would be unwise in general to simply set it to the value corresponding to the target of the longjmp, even though in your particular case you could argue that it would be right). So maybe the best solution would be to temporarily increase max-lisp-eval-depth like we do for call_debugger. Not sure how best to do that, since the way it's done in call_debugger could have too high a performance cost (it's not a problem for call_debugger since that's an exceptional situation). Stefan > You must be noted step 7~10. > Problem's steps: > 1. eval.c:1208:Funwind_protect: record_unwind_protect (unwind_body, XCDR (args)); > 2. eval.c:1209:Funwind_protect: val = eval_sub (XCAR (args)); > 3. eval.c:2090:eval_sub: if (lisp_eval_depth > max_lisp_eval_depth) error ("Lisp nesting exceeds `max-lisp-eval-depth'”); > 4. eval.c:1582:xsignal: Fsignal (error_symbol, data); > 5. eval.c:1558:Fsignal: unwind_to_catch (h, unwind_data); > 6. eval.c:1161:unwind_to_catch: unbind_to (handlerlist->pdlcount, Qnil); > 7. eval.c:3305:unbind_to: unwind_body // specpdl_ptr->unwind_ptr.func (specpdl_ptr->unwind_ptr.arg); > 8. eval.c:476:unwind_body: Fprogn (body); > 9. eval.c:462:Fprogn: val = eval_sub (XCAR (body)); > 10. eval.c:2090:eval_sub: if (lisp_eval_depth > max_lisp_eval_depth) error ("Lisp nesting exceeds `max-lisp-eval-depth’”) > You can avoid this problem using `ignore-errors’ macro. > (eval.c:1175:unwind_to_catch: lisp_eval_depth = catch->lisp_eval_depth;) > ```elisp > (defun endless-recursive () > (endless-recursive)) > (unwind-protect > (ignore-errors (endless-recursive)) > (message "finally")) > ``` >> On Mar 6, 2010, at 5:30 AM, Stefan Monnier <monnier@iro.umontreal.ca> wrote: >> >>> If I trigger a lisp nesting error with an infinite recursion inside a >>> let and an flet binding, then the effects of the flet are not undone, >>> resulting in a change of binding at the top-level. >> >>> (defun g () 'g-orig) >>> (setq a 'a-orig) >> >>> (defun h () >>> (let ((a 'a-new)) >>> (flet ((g () 'g-new)) >>> (h)))) >>> (h) ;; <-- Lisp nesting exceeds `max-lisp-eval-depth' >>> (g) ;; g-new ! >>> a ;; a-orig >> >> I can indeed reproduce it. I'm not sure yet what's going on, but it >> might be due to the "Lisp nesting exceeds `max-lisp-eval-depth'" error >> happening in the unwind-protect code (i.e. while undoing the `g' >> binding). The explanation can't be quite so simple, but my gut feeling >> tells me it's got to do with it. >> >> >> Stefan >> >> >> >> ^ permalink raw reply [flat|nested] 5+ messages in thread
* bug#5662: flet not undone on lisp nesting error 2010-03-01 2:30 bug#5662: flet not undone on lisp nesting error Dan Davison 2010-03-05 20:30 ` Stefan Monnier @ 2016-06-02 1:15 ` Noam Postavsky 1 sibling, 0 replies; 5+ messages in thread From: Noam Postavsky @ 2016-06-02 1:15 UTC (permalink / raw) To: 5662 found 5662 23.4 found 5662 24.3 found 5662 24.5 fixed 5662 25.0.94 close 5662 quit Seems to have been fixed in Emacs 25. I could reproduce in several earlier versions (had to add a (require 'cl) to demo code). ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2016-06-02 1:15 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2010-03-01 2:30 bug#5662: flet not undone on lisp nesting error Dan Davison 2010-03-05 20:30 ` Stefan Monnier 2014-11-11 2:16 ` Jinseop Kim 2014-11-11 15:50 ` Stefan Monnier 2016-06-02 1:15 ` Noam Postavsky
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.