@@ -86,9 +86,9 @@ let thread name f =
86
86
let ctx = with_o1trace ~name ctx in
87
87
match Scheduler. within_context ctx f with
88
88
| Error () ->
89
- failwithf
90
- " timing task `%s` failed, exception reported to parent monitor " name
91
- ( )
89
+ (* Scheduler.within_context will send the actual error to the parent monitor asynchronously.
90
+ * At this point, the thread has crashed, so we just return a Deferred that will never resolve *)
91
+ Deferred. create ( Fn. const () )
92
92
| Ok x ->
93
93
x )
94
94
@@ -102,11 +102,12 @@ let sync_thread name f =
102
102
let start_time = Time_ns. now () in
103
103
let ctx = Scheduler. current_execution_context () in
104
104
let ctx = with_o1trace ~name ctx in
105
- match Scheduler. within_context ctx f with
106
- | Error () ->
107
- failwithf
108
- " sync timing task `%s` failed, exception reported to parent monitor"
109
- name ()
105
+ match
106
+ Scheduler.Private. with_execution_context (Scheduler.Private. t () ) ctx
107
+ ~f: (fun () -> Result. try_with f)
108
+ with
109
+ | Error exn ->
110
+ Exn. reraise exn " exception caught by O1trace.sync_thread"
110
111
| Ok result ->
111
112
let elapsed_time = Time_ns. abs_diff (Time_ns. now () ) start_time in
112
113
on_job_exit' fiber elapsed_time ;
@@ -125,6 +126,12 @@ let () =
125
126
126
127
let % test_module " thread tests" =
127
128
( module struct
129
+ exception Test_exn
130
+
131
+ let is_test_exn exn =
132
+ (* there isn't a great way to compare the exn to the one that was thrown due to how async mangles the exn, so we do this instead *)
133
+ String. is_substring (Exn. to_string exn ) ~substring: " (Test_exn)"
134
+
128
135
let child_of n =
129
136
match
130
137
let prev_sync_fiber = ! current_sync_fiber in
@@ -214,5 +221,31 @@ let%test_module "thread tests" =
214
221
Deferred. unit ) ) ) ;
215
222
Deferred. unit ) ) )
216
223
224
+ let % test_unit " exceptions are handled properly when raised in first cycle \
225
+ of a thread" =
226
+ test (fun stop ->
227
+ match % map
228
+ Monitor. try_with (fun () ->
229
+ thread " test" (fun () -> raise Test_exn ) )
230
+ with
231
+ | Ok _ ->
232
+ failwith " expected a failure"
233
+ | Error exn ->
234
+ assert (is_test_exn exn ) ;
235
+ stop () )
236
+
237
+ let % test_unit " exceptions are handled properly when raised in first cycle \
238
+ of a sync_thread" =
239
+ test (fun stop ->
240
+ match % map
241
+ Monitor. try_with (fun () ->
242
+ sync_thread " test" (fun () -> raise Test_exn ) )
243
+ with
244
+ | Ok _ ->
245
+ failwith " expected a failure"
246
+ | Error exn ->
247
+ assert (is_test_exn exn ) ;
248
+ stop () )
249
+
217
250
(* TODO: recursion tests *)
218
251
end )
0 commit comments