Skip to content

Commit 8c0ce26

Browse files
committed
feat(core): propagate thread exceptions on join
1 parent f4a3d8a commit 8c0ce26

File tree

2 files changed

+54
-17
lines changed

2 files changed

+54
-17
lines changed

Makefile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,8 @@ CORE_SRCS := \
144144
lib/core/io/assistants.scm \
145145
lib/core/io/process.scm \
146146
lib/core/foreign.scm \
147-
lib/core/foreign-library.scm
147+
lib/core/foreign-library.scm \
148+
lib/core/threading.scm
148149

149150
RNRS_SRCS := \
150151
lib/rnrs/base.scm \
@@ -176,7 +177,9 @@ CAPY_SRCS_SLS := \
176177
lib/capy/args/parser.sls \
177178
lib/capy/args/results.sls \
178179
lib/capy/args.sls \
179-
lib/capy/session.sls
180+
lib/capy/session.sls \
181+
lib/capy/deque.sls \
182+
lib/capy/channel.sls
180183

181184
CAPY_SRCS_SCM := \
182185
lib/capy/compiler/tree-il/terms.scm \

lib/core/threading.scm

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,31 @@
1212
mutex-acquire
1313
mutex-release
1414
call-with-new-thread
15-
join-thread)
15+
join-thread
16+
&uncaught-exception
17+
uncaught-exception?
18+
uncaught-exception-reason
19+
&terminated-thread-exception
20+
terminated-thread-exception?
21+
terminated-thread-exception-thread)
1622
(import (core primitives)
17-
(core hashtables))
23+
(core hashtables)
24+
(core conditions)
25+
(core records))
26+
27+
(define-condition-type &uncaught-exception &error
28+
make-uncaught-exception
29+
uncaught-exception?
30+
(reason uncaught-exception-reason))
31+
32+
(define-condition-type terminated-thread-exception &error
33+
make-terminated-thread-exception
34+
terminated-thread-exception?
35+
(thread terminated-thread-exception-thread))
36+
37+
(define-record-type uncaught
38+
(fields
39+
reason))
1840

1941
;; weak hashtable which keeps thread data until thread object is alive
2042
(define %thread-results (make-weak-hashtable))
@@ -27,19 +49,26 @@
2749

2850
(let ([t (fork-thread
2951
(lambda ()
30-
(call-with-values
31-
(lambda ()
32-
(with-mutex mutex
33-
(set! thread (current-thread))
34-
(hashtable-set! %thread-join-data thread (cons cv mutex))
35-
(condition-signal cv))
36-
(with-exception-handler
37-
(lambda (exn) exn)
38-
thunk))
39-
(lambda vals
40-
(with-mutex mutex
41-
(hashtable-set! %thread-results cv vals)
42-
(condition-broadcast cv))))))])
52+
(call/cc
53+
(lambda (return)
54+
(call-with-values
55+
(lambda ()
56+
(with-mutex mutex
57+
(set! thread (current-thread))
58+
(hashtable-set! %thread-join-data thread (cons cv mutex))
59+
(condition-signal cv))
60+
(with-exception-handler
61+
(lambda (exn)
62+
(define obj (make-uncaught exn))
63+
(with-mutex mutex
64+
(hashtable-set! %thread-results cv obj)
65+
(condition-broadcast cv))
66+
(return #f))
67+
thunk))
68+
(lambda vals
69+
(with-mutex mutex
70+
(hashtable-set! %thread-results cv vals)
71+
(condition-broadcast cv))))))))])
4372

4473
(with-mutex mutex
4574
(let loop ()
@@ -51,6 +80,9 @@
5180
(loop)])))))
5281

5382
(define (join-thread thread)
83+
"Wait for thread to terminate and return its values. If exception
84+
was raised in the thread, this function will raise &uncaught-exception
85+
with the original exception as reason."
5486
(define data (hashtable-ref %thread-join-data thread #f))
5587

5688
(unless data
@@ -62,6 +94,8 @@
6294
(cond
6395
[(hashtable-ref %thread-results cv #f) =>
6496
(lambda (res)
97+
(if (uncaught? res)
98+
(raise (make-uncaught-exception (uncaught-reason res))))
6599
(apply values res))]
66100
[else
67101
(condition-wait cv mutex)

0 commit comments

Comments
 (0)