Stephen Compall wrote:
case of undefined behavior: (block a (block b (unwind-protect (return-from a 1) (return-from b 2)))) [1] http://www.lisp.org/HyperSpec/Issues/iss152.html
Steele had a nice text about breathing, roaming and fishing crabs in CLtL1 and II.
I would like to hear from those [...] running CFFI
This has nothing to do with CFFI. Only the underlying implementation knows the answer.
And the general answer is: don't exit non-locally across callbacks! It can always lead to unforeseen trouble.
Rationale: a) Consider jumping to a shared library written in say C++, which has its own idea of unwind-protect. If you throw out of this via Lisp, the C++ destructor will never get called. Different run-times don't mix. b) Consider code written in C. It expects a functional style, i.e. it was not written with non-local exits in mind. It may set some variables or worse, allocate resources, call some function (your Lisp callback) and reset that variable upon exit. If you throw out of this via Lisp, the variable will not be reset, the resource onot freed. Your application may cease to work as a consequence of this (been there, done that). And it will take you time to debug and understand why.
Of course, if you throw out of C:qsort(), I wouldn't expect trouble. That's no counterproof of the above. But consider calling into .NET (I think Edit Weitz has a binding to .NET). Non-local exits get you immediately out of any specified behaviour.
As an aside: would it be better for the defcallback semantics to simply say "don't exit non-locally through a C frame"?
Exactly. It's the only sensible thing to do. Ideally, every callback should contain something similar to ignore-errors (e.g. X event loops).
It would probably make callbacks (and perhaps callouts, for that matter) cheaper to call,
I don't understand that implication.
Regards, Jorg Hohle.