Last weeks I did a full review of our code base of uses of "catch (Throwable" as a means of catching anything and "just continuing from there".
It seems our code was relatively unpredictable, because in some sites it would throw a debugging exeption, whereas in others processing would continue. With the change where ControlTransfer is now an unchecked exception, it turns out most of the try/catch blocks were unnecessary anyway; most of them have been removed or made more specific (IOException, mostly).
The remaining ones seem to have a function, however, everybody is invited to see if I didn't forget or misjudge some locations.
With the removal, there's a new instability, it seems: when using the IGNORE-ERRORS macro, one expects the code inside it to catch all errors and continue processing after it, no matter what the error. However, since we no longer catch Throwable and therefore no longer catch any of the RuntimeExceptions, it turns out IGNORE-ERRORS leaks all runtime exceptions. Arguably it shouldn't leak StackOverflowException and many others: these might be *the* conditions to continue after IGNORE-ERRORS.
So, I think we need to implement some construct to catch all java exceptions raised inside it and convert them to Lisp errors. This can then be included in IGNORE-ERRORS.
Comments?
Bye,
Erik.
On Fri, Dec 25, 2009 at 11:50 PM, Erik Huelsmann ehuels@gmail.com wrote:
Last weeks I did a full review of our code base of uses of "catch (Throwable" as a means of catching anything and "just continuing from there".
It seems our code was relatively unpredictable, because in some sites it would throw a debugging exeption, whereas in others processing would continue. With the change where ControlTransfer is now an unchecked exception, it turns out most of the try/catch blocks were unnecessary anyway; most of them have been removed or made more specific (IOException, mostly).
The remaining ones seem to have a function, however, everybody is invited to see if I didn't forget or misjudge some locations.
With the removal, there's a new instability, it seems: when using the IGNORE-ERRORS macro, one expects the code inside it to catch all errors and continue processing after it, no matter what the error. However, since we no longer catch Throwable and therefore no longer catch any of the RuntimeExceptions, it turns out IGNORE-ERRORS leaks all runtime exceptions. Arguably it shouldn't leak StackOverflowException and many others: these might be *the* conditions to continue after IGNORE-ERRORS.
So, I think we need to implement some construct to catch all java exceptions raised inside it and convert them to Lisp errors. This can then be included in IGNORE-ERRORS.
Through IRC, Ville asks if we need to distinguish between compiler/interpreter cases of IGNORE-ERRORS. Depending on how we implement it: possibly.
Then he goes on to state that when you HANDLER-CASE/HANDLER-BIND SERIOUS-CONDITION (the base type of anything which is normally non-continuable), then you should probably also catch RuntimeExceptions: out-of-memory and out-of-stack and others.
He states that binding JAVA-EXCEPTION for any code which calls Java code should handle them at the very least. Well, I can safely say that's infact the case. However, if you run out of Java stack somewhere in the middle of Lisp code, an out-of-stack exception is generated too, but it's not handled these days by any of the HANDLER-BIND or IGNORE-ERRORS forms in any of the enclosing/calling forms. So, my point wasn't as much about our interfacing with Java code, but more about where to catch errors from Lisp code.
I imagine that with the right enhancement construct in the interpreter/compiler, we could inject well specified points in our code where Java exceptions get converted to Lisp errors.
If we decide to go that way however, a new question arises: what to do if the handler-bind *doesn't* bind the specific error? Should the Lisp mechanism kick in? (that is: pass the error to outer handlers) or should the original error be rethrown?
Comments?
Well, it's great to be able to discuss: the outcome should at least be less random than what we used to see in our code before.
Bye,
Erik.
2009/12/28 Erik Huelsmann ehuels@gmail.com:
I imagine that with the right enhancement construct in the interpreter/compiler, we could inject well specified points in our code where Java exceptions get converted to Lisp errors. If we decide to go that way however, a new question arises: what to do if the handler-bind *doesn't* bind the specific error? Should the Lisp mechanism kick in? (that is: pass the error to outer handlers) or should the original error be rethrown?
Well, if an error is unhandled with the current implementation, we land in the debugger, right? What I'd like to have is some means to tell abcl whether the debugger or a rethrow is wanted. Lisp programs don't really have any option besides the debugger, other than terminating (and we might want to support that too), but java programs embedding lisp programs may be capable of recovering from exceptions/errors unhandled on the lisp side.
As hopefully captured by your recap of my irc comments, I think ignore-errors should catch everything, and not leak. Same goes for casing/binding serious-condition (or condition, obviously, since it's the base type). We then have to decide what role java-condition plays, and I think we should keep it as a means to handle exceptions raised by java functions that are called from lisp code. That's a bit vague, obviously, since it's then hard to draw the line as to whether a RuntimeException manifests as java-exception or as a condition. The answer to that line-drawing depends on whether we have a condition type for StackOverflow and NPE and NoMemory. I'm inclined to think that the aforementioned exceptions map to java-condition. The base types of java-exception are then enough for more lispy code, and I think print methods take care of serializing into string format if need be.
Did that make sense?
armedbear-devel@common-lisp.net