How to print an exception with a stack trace?

Tomas Volf <[email protected]> Mon, 29 Dec 2025 22:59:09 +0100
Newsgroups gmane.lisp.guile.user
Message-ID <[email protected]>
--=-=-=
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable

Hello,

I am trying to print a stack trace when I handle an exception from a
procedure my code is invoking.  I put together following code:

=2D-8<---------------cut here---------------start------------->8---
(define-module (exc)
  #:use-module (ice-9 exceptions))

(define-exception-type &stack &error
  make-exception-with-stack exception-with-stack?
  (stack exception-with-stack-stack))

(define (foo)
  (1+ (bar)))

(define (bar)
  (1+ (baz)))

(define* (baz #:optional val)
  (if val
      val
      (raise-exception
       (make-exception (make-error)
                       (make-exception-with-message "Message.")
                       (make-exception-with-irritants '(1 2 3))))))

(define-public (main _)
  (with-exception-handler (=CE=BB (exc)
                            (print-exception (current-error-port)
                                             #f
                                             '%exception
                                             (list exc))
                            (display-backtrace (exception-with-stack-stack =
exc)
                                               (current-error-port)
                                               0))
    (=CE=BB ()
      (with-exception-handler
          (=CE=BB (exc)
            (let ((stack (make-stack #t)))
              (raise-exception
               (make-exception exc
                               (make-exception-with-stack stack)))))
        (=CE=BB ()
          (foo))))
    #:unwind? #t))
=2D-8<---------------cut here---------------end--------------->8---

When I run the script, I get the following output:

=2D-8<---------------cut here---------------start------------->8---
$ GUILE_AUTO_COMPILE=3D0 guild compile -W3 -O0 -o /tmp/exc/exc.go /tmp/exc/=
exc.scm
/tmp/exc/exc.scm:4:0: warning: possibly unused local top-level variable `ex=
ception-with-stack?'
wrote `/tmp/exc/exc.go'
$ GUILE_AUTO_COMPILE=3D0 guile -L /tmp/exc -C /tmp/exc -e '(exc)' -c ''
ERROR:
  1. &error
  2. &message: "Message."
  3. &irritants: (1 2 3)
  4. &stack: #<stack 7f22e2cbad40>
In ice-9/boot-9.scm:
  1752:10 10 (with-exception-handler _ _ #:unwind? _ #:unwind-for-type _)
In unknown file:
           9 (apply-smob/0 #<thunk 7f22e2ca0300>)
In ice-9/boot-9.scm:
    724:2  8 (call-with-prompt ("prompt") #<procedure 7f22e2cb1200 at ice-9=
/eval.scm:330:=E2=80=A6> =E2=80=A6)
In ice-9/eval.scm:
    619:8  7 (_ #(#(#<directory (guile-user) 7f22e2ca3c80>)))
In ice-9/boot-9.scm:
  1747:15  6 (with-exception-handler #<procedure 7f22d9807978 at /tmp/exc/e=
xc.scm:23:26 (=E2=80=A6> =E2=80=A6)
  1752:10  5 (with-exception-handler _ _ #:unwind? _ #:unwind-for-type _)
In /tmp/exc/exc.scm:
      9:6  4 (foo)
     12:6  3 (bar)
In ice-9/boot-9.scm:
  1685:16  2 (raise-exception _ #:continuable? _)
In /tmp/exc/exc.scm:
    34:25  1 (_ #<&compound-exception components: (#<&error> #<&message mes=
sage: "Message.=E2=80=A6>)
In unknown file:
           0 (make-stack #t)
=2D-8<---------------cut here---------------end--------------->8---

I have few question I hope someone here will be able to help me with.

1. Is the double with-exception-handler

  (with-exception-handler print-exc
    (=CE=BB ()
      (with-exception-handler capture-stack-and-re-raise
        thunk))
    #:unwind? #t)

the best solution, or is there some more elegant way?

2. The stack print above does not show the `baz' procedure at all.  Am I
doing something wrong?  Should the stack capture be done in a different
manner?

3. How can I actually print the stack using the print-exception?  The
procedure is described as "an extensible exception printer", but

  (set-exception-printer! &stack (=CE=BB (exc) (pk exc)))

did not seem to actually do anything.  So how can I provide custom
printers for my exception type, how can I extend the printer?

4. Am I just reinventing already made wheel?  Is there something
built-in I should be using instead?

Happy Christmas,
Tomas

=2D-=20
There are only two hard things in Computer Science:
cache invalidation, naming things and off-by-one errors.

--=-=-=
Content-Type: application/pgp-signature; name="signature.asc"

-----BEGIN PGP SIGNATURE-----

iQJCBAEBCgAsFiEEt4NJs4wUfTYpiGikL7/ufbZ/wakFAmlS+a0OHH5Ad29sZnNk
ZW4uY3oACgkQL7/ufbZ/waldmQ//YIiNRuK9tIfoZWFgTLQVPC0riKB6+faOdwrG
XsTL9R59ZycDZHTtelTvJ9NKWaHiEPHPP+mV0xHcMPYVFUGO2D7+4aj7QcQjUllG
S4QKC5U+1oN9yqNMzQdW6gH39s9HTROPpl3Uib4V5kcCOUFpCnVM6XzX/VyByAr4
AXFmUPIABraDO3+kfecBgalD8cuEU/acSChdeQqy/Ji0qxNpZzEKsSbCppb+ZylT
urO8OXVRoKg5Uc4CAmOaF7Z7+CGJ7tTQ5RjsDz5ToYb1LXt4+UCJijpyiwsMVfhp
4wTB9PlkFspq2rktzQMqRomYyShT0crSnv2s22Mxbpna+eT4+/3fUjYOUCXvE35m
LRn4B32nh6MB7+t5fGOftdQS8kEWtIAkr+7AUXqKmjkrntwWxYMoGMtijAdJye0F
B+Z/YaRQQ265CcYGdbw25ZpBpRRM7i3C8+loWGnifYfGqeGCXv+Z7X2dXYb9AUQ2
vpfO5HcTLrlw8i5e+sfLrSXUkEGGh4b+iqRg9co4BVV2ct3iE59r+og7arm419A3
ZvjuWCRlk23P+0oCIItd1/kAZMYrExgTeGDkSutTJHAFJAZeG5QjA/RhcNnLpkT1
bynVuTnRVA8/AfNt2rVb+4DFWbXlFrrO/iYtAVLL+Vk3uh2hP6pRM50G+s5jsLuX
MhIMkbM=
=J5q6
-----END PGP SIGNATURE-----
--=-=-=--