chicken-scheme

Trace an exception


Suppose this simple loop in a child thread that executes step every second, while you can interact with via a REPL (inspect state or change step):

(import (srfi 18) (chicken repl))

(define mutex (make-mutex))
(define (with-mutex-locked mutex thunk) (dynamic-wind
    (lambda () (mutex-lock! mutex))
    (lambda () (thunk))
    (lambda () (mutex-unlock! mutex))))

(set! state 0)
(define (step) (set! state (+ state 1)))

(define (loop)
    (with-mutex-locked mutex step)
    (sleep 1)
    (loop))

(thread-start! loop)
(repl (lambda (x) (with-mutex-locked mutex (lambda () (eval x)))))
(exit)

However, when changing step to something erroneous the thread crashes and prints a trace:

(define (step) (car `()))
Warning (#<thread: thread26>): in thread: (car) bad argument type: ()

    Call history:

    <eval>    [loop] (loop)
    <eval>    [loop] (dynamic-wind (lambda () (mutex-lock! mutex)) (lambda () (step)) (lambda () (mutex-unlock! mutex)))
    <eval>    [loop] (mutex-lock! mutex)
    <eval>    [loop] (step)
    <eval>    [step] (car (quasiquote ()))  <--

I'd like to recover (i.e. unlock the mutex, restart the loop) from such a crash but still have the error with its trace printed for debugging. My attempt with (handle-exceptions … (step)) didn't work out, as the exception apparently only contains message, arguments and location – not the trace. But the trace must be hidden somewhere, otherwise the interpreter couldn't print it. Is there a way to access it? Or is there another way to recover after the trace got printed?


Solution

  • The trace buffer is a ring buffer containing just the most recent calls. It can't be used to jump back.

    You might want to read this old CHICKEN Gazette issue which contains a tutorial (search for "omelette recipes") on how exception handling works and the difference between continuable and non-continuable exceptions. If you're in a hurry, the real explanation starts at "To continue or not continue -- That's the question".