[racket] Breaks always go to main thread?
Preface to avoid any "XY problem": I recently added errortrace support
to racket-mode. But I noticed that C-c is bypassing this. Which is sad;
definitely want good context for that -- not "running body".
Digging in, it seems that exn:break is only ever given to the main
thread.
[This matters because the user program is running on a child thread (as
with racket/sandbox or the eventspace-handler-thread in DrR). The
interesting errortrace info is on/about the child thread. The main
thread is just sitting on a sync.]
I didn't realize that exn:break is unlike exn:fail (other exn's
generally?) in this respect.
As a distilled example:
#lang racket/base
(thread
(λ ()
(with-handlers ([exn:fail?
(λ _ (displayln "Fail caught in sub thread. Yay!"))])
(/ 1 0))))
(thread
(λ ()
(with-handlers ([exn:break? ;never gets here
(λ _ (displayln "Break caught in sub thread. Yay!"))])
(displayln "Press C-c")
(let loop ([n 0])
(displayln n)
(sleep 1)
(loop (add1 n))))))
(with-handlers ([exn:break?
(λ _ (displayln "Break caught in main thread. Boo!"))])
(sync never-evt))
Running it:
#<thread:/tmp/break.rkt:3:8>
#<thread:/tmp/break.rkt:8:8>
Press C-c
0
Fail caught in sub thread. Yay!
1
2
C-c C-cBreak caught in main thread. Boo!
After some pondering and doc-re-reading, my only idea is to catch the
exn:break in the main thread, and break-thread the child thread, to
catch it there, too. For example:
(define thd
(thread
(λ ()
(with-handlers ([exn:break?
(λ _ (displayln "Break caught in sub thread. Yay!"))])
(displayln "Press C-c")
(let loop ([n 0])
(displayln n)
(sleep 1)
(loop (add1 n)))))))
(with-handlers ([exn:break?
(λ _
(break-thread thd)
(sleep))])
(sync never-evt))
Running it:
racket -t /tmp/break.rkt
Press C-c
0
1
C-c C-cBreak caught in sub thread. Yay!
So, "it works". And now racket-mode shows the full errortrace on a
break, apparently fixing the bug.
But do I understand this correctly? I'm cautious generally, but also
specifically because I didn't see this described in the main docs --
that exn:break is only ever given to the main thread.
Any caveats, cautions, advice?