Subject: RE: exception from inside false-if-exception?

From: Attila Lendvai <[email-masked]>
Date: Wed, 12 Jun 2024 16:32:03 +0000

i was once again hindered by this, so i digged deeper.

please find a test.scm attached.

looks like (R6RS) WITH-EXCEPTION-HANDLER has such a surprising semantics that i didn't even consider that to be the case. some hours later i found this:

https://practical-scheme.net/gauche/man/gauche-refe/Exceptions.html#index-with_002dexception_002dhandler

"Note: SRFI-18 specifies the exception handler installed with with-exception-handler will be called with exactly the same dynamic environment, including the exception handler settings. It means if an exception is raised within the handler, it will be caught with the same handler."

"However, the bare SRFI-18 semantics turned out to be error prone–users tended to assume errors from a handler would be handled by outer handler, and were perplexed when they ran into infinite recursion of handlers"

now, as surprising as the above was to me, guile behaves in a yet more surprising way, because seeing a stack overflow would have hinted the above semantics to me.

instead, what seems to be happening (?) is that there's some short-circuit somewhere in the guile codebase that aborts this infinite recursion by printing a backtrace and the exception... and then continues who knows where, and with what return value? unfortunately, it doesn't print anything else to explain the situation, or to grep for in the codebase.

context:
--------

in the original context of shepherd, it doesn't seem to just entirely exit the process, because shepherd continues to run, and IIRC it even functions to some extent. and it doesn't seem to just exit the current thread either, because IIUC shepherd is a single-threaded app (using fibers).

for reference, i'm including the output at the end of this mail that i'm seeing in my shepherd branch. note that it says "Uncaught exception in task:" which suggests that this exception seems to have left a fiber and reached fiber's RUN-SCHEDULER/ERROR-HANDLING.

and finally, my ultimate use-case is a CALL-WITH-ERROR-HANDLING function that does not unwind, and has three layers of nested error handlers to log any errors with a backtrace, including errors in the user supplied error handlers, or in the logging subsystem.

i see two actionables:
----------------------

if i'm not wrong in the above, then:

please add some message -- any message -- to this short-circuit code.

please extend the doc of WITH-EXCEPTION-HANDLER with a warning that explains the dynamic extent of the binding of the handler at the time the handler is called, and any possible short circuits installed in guile against that.

-- 
• attila lendvai
• PGP: 963F 5D5F 45C7 DFCD 0A39
--
“The strength of a person's spirit would then be measured by how much 'truth' he could tolerate, or more precisely, to what extent he needs to have it diluted, disguised, sweetened, muted, falsified.”
	— Friedrich Nietzsche (1844–1900), 'Beyond Good and Evil' (1886)

Uncaught exception in task:
In fibers.scm:
    172:8 13 (_)
In shepherd/service.scm:
    425:9 12 (_)
In ice-9/boot-9.scm:
  1752:10 11 (with-exception-handler _ _ #:unwind? _ # _)
In shepherd/service.scm:
   570:31 10 (service-controller #<service bee-1> #<<channel> getq: ?>)
In /gnu/store/0zd8bv4hmrfqhzb5qv6flslah0a7bplb-shepherd-bee-1.scm:
   1:3579  9 (_ _ . _)
In ice-9/boot-9.scm:
  1685:16  8 (raise-exception _ #:continuable? _)
  1752:10  7 (with-exception-handler _ _ #:unwind? _ # _)
In shepherd/support.scm:
    644:4  6 (log-with-backtrace _ #<&compound-exception componen?> . #)
In unknown file:
           5 (display-backtrace #<stack 7fee5677e9e0> #<output: str?> ?)
In system/repl/debug.scm:
   148:36  4 (print-frames #(#<frame 7fee564e3220 make-stack> #<?> ?) ?)
In ice-9/boot-9.scm:
   2137:6  3 (_)
  1747:15  2 (with-exception-handler #<procedure 7fee566a4780 at ic?> ?)
In system/repl/debug.scm:
    72:40  1 (_)
In ice-9/boot-9.scm:
  1685:16  0 (raise-exception _ #:continuable? _)
ice-9/boot-9.scm:1685:16: In procedure raise-exception:
In procedure string->number: Wrong type argument in position 1 (expecting string): #f