Sorry, I am replying to my message because I'm not on guile-devel, it seems. I'll join later.
Thanks for clarifying that. The misleading statement in the manual is just above the paragraph you quote: on https://www.gnu.org/software/guile/manual/html_node/Catch.html#Catch
Handler is invoked outside the scope of its own
again throws to the same key, a new handler
from further up the
call chain is invoked.
It doesn't mention pre_unwind_handler, which implies that the statement does _not_ apply to pre_unwind_handler. So this should be amended.
But it would be more useful if there were a way to allow a throw to be aborted as I was expecting. How hard would that be to implement? If you think the semantics are in fact different, it could be given a new name, scm_c_catch_and_rethrow or something. What I want is something like BSD signals semantics, where the handler is not reset when the signal occurs.
You ask "In your code, the pre-unwind handler calls failwith() and doesn't expect it to return - so where does it jump to?"
I thought I had explained that, sorry. The call to failwith() does a C longjmp back into the CAML bytecode interpreter (i.e. back down below the call stack into caml_main). This is not a non-local exit, as far as Guile is concerned, because it is just a 'naked' C longjmp. So in that sense, the second time Guile throws an exception it is being thrown from within pre_unwind_handler.