Skip to content

Commit 9ce9425

Browse files
committed
[ty] Abort process if worker thread panics
1 parent 0ede831 commit 9ce9425

File tree

3 files changed

+32
-4
lines changed

3 files changed

+32
-4
lines changed

Cargo.lock

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/ty_server/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ jod-thread = { workspace = true }
2626
lsp-server = { workspace = true }
2727
lsp-types = { workspace = true }
2828
rustc-hash = { workspace = true }
29+
salsa = { workspace = true }
2930
serde = { workspace = true }
3031
serde_json = { workspace = true }
3132
shellexpand = { workspace = true }

crates/ty_server/src/server/schedule/thread/pool.rs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
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;
1618
use std::{
1719
num::NonZeroUsize,
1820
sync::{
@@ -21,8 +23,6 @@ use std::{
2123
},
2224
};
2325

24-
use crossbeam::channel::{Receiver, Sender};
25-
2626
use super::{Builder, JoinHandle, ThreadPriority};
2727

2828
pub(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

Comments
 (0)