[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#5662: flet not undone on lisp nesting error
From: |
Jinseop Kim |
Subject: |
bug#5662: flet not undone on lisp nesting error |
Date: |
Tue, 11 Nov 2014 11:16:48 +0900 |
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
>
>
>
>
- bug#5662: flet not undone on lisp nesting error,
Jinseop Kim <=