Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/proc-macro-api/src/bidirectional_protocol.rs')
-rw-r--r--crates/proc-macro-api/src/bidirectional_protocol.rs17
1 files changed, 14 insertions, 3 deletions
diff --git a/crates/proc-macro-api/src/bidirectional_protocol.rs b/crates/proc-macro-api/src/bidirectional_protocol.rs
index 8311df23d7..ba59cb219b 100644
--- a/crates/proc-macro-api/src/bidirectional_protocol.rs
+++ b/crates/proc-macro-api/src/bidirectional_protocol.rs
@@ -2,6 +2,7 @@
use std::{
io::{self, BufRead, Write},
+ panic::{AssertUnwindSafe, catch_unwind},
sync::Arc,
};
@@ -55,9 +56,19 @@ pub fn run_conversation(
return Ok(BidirectionalMessage::Response(response));
}
BidirectionalMessage::SubRequest(sr) => {
- let resp = callback(sr)?;
- let reply = BidirectionalMessage::SubResponse(resp);
- let encoded = postcard::encode(&reply).map_err(wrap_encode)?;
+ // TODO: Avoid `AssertUnwindSafe` by making the callback `UnwindSafe` once `ExpandDatabase`
+ // becomes unwind-safe (currently blocked by `parking_lot::RwLock` in the VFS).
+ let resp = match catch_unwind(AssertUnwindSafe(|| callback(sr))) {
+ Ok(Ok(resp)) => BidirectionalMessage::SubResponse(resp),
+ Ok(Err(err)) => BidirectionalMessage::SubResponse(SubResponse::Cancel {
+ reason: err.to_string(),
+ }),
+ Err(_) => BidirectionalMessage::SubResponse(SubResponse::Cancel {
+ reason: "callback panicked or was cancelled".into(),
+ }),
+ };
+
+ let encoded = postcard::encode(&resp).map_err(wrap_encode)?;
postcard::write(writer, &encoded)
.map_err(wrap_io("failed to write sub-response"))?;
}