Condition handler changes inside a with-handler code body
Closed this issue · 9 comments
When executing this code:
(defun handler (condition)
(continue-condition condition "continued"))
(with-handler #'handler
(print (cerror "foo" "bar"))
(print (cerror "herp" "derp")))
The first cerror
call is continued as expected, and prints "continued".
The second cerror
call triggers the debugger when it attempts to continue.
looking at the code in error.c
Lines 645 to 651 in 1f4c3ff
It appears that the latest handler is popped off globally every time
signal-condition
is called.
The specification states that
This newly established handler is active throughout execution of its associated body of code unless shadowed by another use of with-handler.
So the handler should stay the same between the two cerror
calls, and "continued" should be printed twice.
Thanks for the report. I ponder
Fixed. Is the fixe working?
Unfortunately not, I'm afraid.
According to the specification:
A handler may defer to previously established handlers by calling signal-condition on the condition object which it received as an argument.
So the below code should print:
"inner handler continued"
"inner handler continued"
"outer handler continued"
(defglobal error-count 0)
(defun outer-handler (condition)
(continue-condition condition "outer handler continued"))
(defun inner-handler (condition)
(if (< error-count 2)
(progn
(setf error-count (+ error-count 1))
(continue-condition condition "inner handler continued"))
(signal-condition condition (condition-continuable condition))))
(defun foo ()
(with-handler #'outer-handler
(with-handler #'inner-handler
(print (cerror "foo" "bar"))
(print (cerror "herp" "derp"))
(print (cerror "bing" "bong")))))
Instead, this code crashes eisl
because it calls the inner handler forever when the last error is signaled.
Thank you. I will try again.
I fixed. is it working?
I found another bug:
The code below should print:
"handled"
"handled"
Instead it prints "handled"
one time and triggers the debugger. This seems to be related to how error handlers are popped off when signal-condition
is called.
(defun handler (condition)
(throw 'tag "handled"))
(defun baz ()
(with-handler #'handler
(print (catch 'tag
(error "error")))
(print (catch 'tag
(error "error")))))
Fixed.
Easy-ISLisp Ver2.93
> (load "tests/bug.lsp")
T
> (baz)
"handled"
"handled"
NIL
>
Thank you for your hard work, Mr. Sasagawa. Everything seems to work now.
Thank you for your help in fixing the bug.