aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_lsp_server/src
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-10-24 07:52:32 +0100
committerAleksey Kladov <[email protected]>2019-10-24 07:56:30 +0100
commit418fbc8662d4a70e5081cc422b4bc8ded4b923d8 (patch)
treee14e06b23baba917d8ea8a2d9de56affb52120aa /crates/ra_lsp_server/src
parent31d84bce3c2ae8bf2a8b3dfaf831bd78f99e0d67 (diff)
don't die if a sync task panics
Diffstat (limited to 'crates/ra_lsp_server/src')
-rw-r--r--crates/ra_lsp_server/src/main_loop.rs16
1 files changed, 10 insertions, 6 deletions
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs
index 0b5d9c44d..1a87706fe 100644
--- a/crates/ra_lsp_server/src/main_loop.rs
+++ b/crates/ra_lsp_server/src/main_loop.rs
@@ -4,7 +4,7 @@ mod handlers;
4mod subscriptions; 4mod subscriptions;
5pub(crate) mod pending_requests; 5pub(crate) mod pending_requests;
6 6
7use std::{error::Error, fmt, path::PathBuf, sync::Arc, time::Instant}; 7use std::{error::Error, fmt, panic, path::PathBuf, sync::Arc, time::Instant};
8 8
9use crossbeam_channel::{select, unbounded, RecvError, Sender}; 9use crossbeam_channel::{select, unbounded, RecvError, Sender};
10use lsp_server::{Connection, ErrorCode, Message, Notification, Request, RequestId, Response}; 10use lsp_server::{Connection, ErrorCode, Message, Notification, Request, RequestId, Response};
@@ -565,7 +565,7 @@ impl<'a> PoolDispatcher<'a> {
565 ) -> Result<&mut Self> 565 ) -> Result<&mut Self>
566 where 566 where
567 R: req::Request + 'static, 567 R: req::Request + 'static,
568 R::Params: DeserializeOwned + Send + 'static, 568 R::Params: DeserializeOwned + panic::UnwindSafe + 'static,
569 R::Result: Serialize + 'static, 569 R::Result: Serialize + 'static,
570 { 570 {
571 let (id, params) = match self.parse::<R>() { 571 let (id, params) = match self.parse::<R>() {
@@ -574,8 +574,12 @@ impl<'a> PoolDispatcher<'a> {
574 return Ok(self); 574 return Ok(self);
575 } 575 }
576 }; 576 };
577 let result = f(self.world, params); 577 let world = panic::AssertUnwindSafe(&mut *self.world);
578 let task = result_to_task::<R>(id, result); 578 let task = panic::catch_unwind(move || {
579 let result = f(world.0, params);
580 result_to_task::<R>(id, result)
581 })
582 .map_err(|_| format!("sync task {:?} panicked", R::METHOD))?;
579 on_task(task, self.msg_sender, self.pending_requests, self.world); 583 on_task(task, self.msg_sender, self.pending_requests, self.world);
580 Ok(self) 584 Ok(self)
581 } 585 }
@@ -610,7 +614,7 @@ impl<'a> PoolDispatcher<'a> {
610 fn parse<R>(&mut self) -> Option<(RequestId, R::Params)> 614 fn parse<R>(&mut self) -> Option<(RequestId, R::Params)>
611 where 615 where
612 R: req::Request + 'static, 616 R: req::Request + 'static,
613 R::Params: DeserializeOwned + Send + 'static, 617 R::Params: DeserializeOwned + 'static,
614 { 618 {
615 let req = self.req.take()?; 619 let req = self.req.take()?;
616 let (id, params) = match req.extract::<R::Params>(R::METHOD) { 620 let (id, params) = match req.extract::<R::Params>(R::METHOD) {
@@ -647,7 +651,7 @@ impl<'a> PoolDispatcher<'a> {
647fn result_to_task<R>(id: RequestId, result: Result<R::Result>) -> Task 651fn result_to_task<R>(id: RequestId, result: Result<R::Result>) -> Task
648where 652where
649 R: req::Request + 'static, 653 R: req::Request + 'static,
650 R::Params: DeserializeOwned + Send + 'static, 654 R::Params: DeserializeOwned + 'static,
651 R::Result: Serialize + 'static, 655 R::Result: Serialize + 'static,
652{ 656{
653 let response = match result { 657 let response = match result {