1313//! The thread pool is implemented entirely using
1414//! the threading utilities in [`crate::server::schedule::thread`].
1515
16+ use crossbeam:: channel:: { Receiver , Sender } ;
17+ use std:: panic:: AssertUnwindSafe ;
1618use std:: {
1719 num:: NonZeroUsize ,
1820 sync:: {
@@ -21,8 +23,6 @@ use std::{
2123 } ,
2224} ;
2325
24- use crossbeam:: channel:: { Receiver , Sender } ;
25-
2626use super :: { Builder , JoinHandle , ThreadPriority } ;
2727
2828pub ( crate ) struct Pool {
@@ -71,7 +71,33 @@ impl Pool {
7171 current_priority = job. requested_priority ;
7272 }
7373 extant_tasks. fetch_add ( 1 , Ordering :: SeqCst ) ;
74- ( job. f ) ( ) ;
74+
75+ // SAFETY: it's safe to assume that `job.f` is unwind safe because we always
76+ // abort the process if it panics.
77+ // Panicking here ensures that we don't swallow errors and is the same as
78+ // what rayon does.
79+ // Any recovery should be implemented outside the thread pool (e.g. when
80+ // dispatching requests/notifications etc).
81+ if let Err ( error) = std:: panic:: catch_unwind ( AssertUnwindSafe ( job. f ) ) {
82+ if let Some ( msg) = error. downcast_ref :: < String > ( ) {
83+ tracing:: error!( "Worker thread panicked with: {msg}; aborting" ) ;
84+ } else if let Some ( msg) = error. downcast_ref :: < & str > ( ) {
85+ tracing:: error!( "Worker thread panicked with: {msg}; aborting" ) ;
86+ } else if let Some ( cancelled) =
87+ error. downcast_ref :: < salsa:: Cancelled > ( )
88+ {
89+ tracing:: error!(
90+ "Worker thread got cancelled: {cancelled}; aborting"
91+ ) ;
92+ } else {
93+ tracing:: error!(
94+ "Worker thread panicked with: {error:?}; aborting"
95+ ) ;
96+ }
97+
98+ std:: process:: abort ( ) ;
99+ }
100+
75101 extant_tasks. fetch_sub ( 1 , Ordering :: SeqCst ) ;
76102 }
77103 }
0 commit comments