diff options
Diffstat (limited to 'crates/ra_lsp_server')
-rw-r--r-- | crates/ra_lsp_server/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main.rs | 10 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop.rs | 6 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/project_model.rs | 10 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/thread_watcher.rs | 81 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/vfs.rs | 7 | ||||
-rw-r--r-- | crates/ra_lsp_server/tests/heavy_tests/support.rs | 6 |
8 files changed, 19 insertions, 103 deletions
diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml index 133decc52..30a8d35cd 100644 --- a/crates/ra_lsp_server/Cargo.toml +++ b/crates/ra_lsp_server/Cargo.toml | |||
@@ -26,6 +26,7 @@ text_unit = { version = "0.1.2", features = ["serde"] } | |||
26 | smol_str = { version = "0.1.5", features = ["serde"] } | 26 | smol_str = { version = "0.1.5", features = ["serde"] } |
27 | rustc-hash = "1.0" | 27 | rustc-hash = "1.0" |
28 | 28 | ||
29 | thread_worker = { path = "../thread_worker" } | ||
29 | ra_syntax = { path = "../ra_syntax" } | 30 | ra_syntax = { path = "../ra_syntax" } |
30 | ra_editor = { path = "../ra_editor" } | 31 | ra_editor = { path = "../ra_editor" } |
31 | ra_text_edit = { path = "../ra_text_edit" } | 32 | ra_text_edit = { path = "../ra_text_edit" } |
diff --git a/crates/ra_lsp_server/src/lib.rs b/crates/ra_lsp_server/src/lib.rs index 75c6fa1b8..1d7258c35 100644 --- a/crates/ra_lsp_server/src/lib.rs +++ b/crates/ra_lsp_server/src/lib.rs | |||
@@ -5,7 +5,6 @@ mod path_map; | |||
5 | mod project_model; | 5 | mod project_model; |
6 | pub mod req; | 6 | pub mod req; |
7 | mod server_world; | 7 | mod server_world; |
8 | pub mod thread_watcher; | ||
9 | mod vfs; | 8 | mod vfs; |
10 | 9 | ||
11 | pub type Result<T> = ::std::result::Result<T, ::failure::Error>; | 10 | pub type Result<T> = ::std::result::Result<T, ::failure::Error>; |
diff --git a/crates/ra_lsp_server/src/main.rs b/crates/ra_lsp_server/src/main.rs index 9ba972562..4497980e5 100644 --- a/crates/ra_lsp_server/src/main.rs +++ b/crates/ra_lsp_server/src/main.rs | |||
@@ -6,11 +6,11 @@ use ra_lsp_server::Result; | |||
6 | 6 | ||
7 | fn main() -> Result<()> { | 7 | fn main() -> Result<()> { |
8 | ::std::env::set_var("RUST_BACKTRACE", "short"); | 8 | ::std::env::set_var("RUST_BACKTRACE", "short"); |
9 | Logger::with_env_or_str("error") | 9 | let logger = Logger::with_env_or_str("error").duplicate_to_stderr(Duplicate::All); |
10 | .duplicate_to_stderr(Duplicate::All) | 10 | match ::std::env::var("RA_INTERNAL_MODE") { |
11 | .log_to_file() | 11 | Ok(ref v) if v == "1" => logger.log_to_file().directory("log").start()?, |
12 | .directory("log") | 12 | _ => logger.start()?, |
13 | .start()?; | 13 | }; |
14 | log::info!("lifecycle: server started"); | 14 | log::info!("lifecycle: server started"); |
15 | match ::std::panic::catch_unwind(main_inner) { | 15 | match ::std::panic::catch_unwind(main_inner) { |
16 | Ok(res) => { | 16 | Ok(res) => { |
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index 41f70f263..eab82ee85 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs | |||
@@ -10,6 +10,7 @@ use gen_lsp_server::{ | |||
10 | use languageserver_types::NumberOrString; | 10 | use languageserver_types::NumberOrString; |
11 | use ra_analysis::{Canceled, FileId, LibraryData}; | 11 | use ra_analysis::{Canceled, FileId, LibraryData}; |
12 | use rayon; | 12 | use rayon; |
13 | use thread_worker::Worker; | ||
13 | use threadpool::ThreadPool; | 14 | use threadpool::ThreadPool; |
14 | use rustc_hash::FxHashSet; | 15 | use rustc_hash::FxHashSet; |
15 | use serde::{de::DeserializeOwned, Serialize}; | 16 | use serde::{de::DeserializeOwned, Serialize}; |
@@ -21,7 +22,6 @@ use crate::{ | |||
21 | project_model::{workspace_loader, CargoWorkspace}, | 22 | project_model::{workspace_loader, CargoWorkspace}, |
22 | req, | 23 | req, |
23 | server_world::{ServerWorld, ServerWorldState}, | 24 | server_world::{ServerWorld, ServerWorldState}, |
24 | thread_watcher::Worker, | ||
25 | vfs::{self, FileEvent}, | 25 | vfs::{self, FileEvent}, |
26 | Result, | 26 | Result, |
27 | }; | 27 | }; |
@@ -92,8 +92,8 @@ pub fn main_loop( | |||
92 | let ws_res = ws_watcher.stop(); | 92 | let ws_res = ws_watcher.stop(); |
93 | 93 | ||
94 | main_res?; | 94 | main_res?; |
95 | fs_res?; | 95 | fs_res.map_err(|_| format_err!("fs watcher died"))?; |
96 | ws_res?; | 96 | ws_res.map_err(|_| format_err!("ws watcher died"))?; |
97 | 97 | ||
98 | Ok(()) | 98 | Ok(()) |
99 | } | 99 | } |
diff --git a/crates/ra_lsp_server/src/project_model.rs b/crates/ra_lsp_server/src/project_model.rs index cb91ada90..b881f8b6f 100644 --- a/crates/ra_lsp_server/src/project_model.rs +++ b/crates/ra_lsp_server/src/project_model.rs | |||
@@ -4,11 +4,9 @@ use cargo_metadata::{metadata_run, CargoOpt}; | |||
4 | use ra_syntax::SmolStr; | 4 | use ra_syntax::SmolStr; |
5 | use rustc_hash::{FxHashMap, FxHashSet}; | 5 | use rustc_hash::{FxHashMap, FxHashSet}; |
6 | use failure::{format_err, bail}; | 6 | use failure::{format_err, bail}; |
7 | use thread_worker::{WorkerHandle, Worker}; | ||
7 | 8 | ||
8 | use crate::{ | 9 | use crate::Result; |
9 | Result, | ||
10 | thread_watcher::{ThreadWatcher, Worker}, | ||
11 | }; | ||
12 | 10 | ||
13 | /// `CargoWorksapce` represents the logical structure of, well, a Cargo | 11 | /// `CargoWorksapce` represents the logical structure of, well, a Cargo |
14 | /// workspace. It pretty closely mirrors `cargo metadata` output. | 12 | /// workspace. It pretty closely mirrors `cargo metadata` output. |
@@ -199,8 +197,8 @@ impl TargetKind { | |||
199 | } | 197 | } |
200 | } | 198 | } |
201 | 199 | ||
202 | pub fn workspace_loader() -> (Worker<PathBuf, Result<CargoWorkspace>>, ThreadWatcher) { | 200 | pub fn workspace_loader() -> (Worker<PathBuf, Result<CargoWorkspace>>, WorkerHandle) { |
203 | Worker::<PathBuf, Result<CargoWorkspace>>::spawn( | 201 | thread_worker::spawn::<PathBuf, Result<CargoWorkspace>, _>( |
204 | "workspace loader", | 202 | "workspace loader", |
205 | 1, | 203 | 1, |
206 | |input_receiver, output_sender| { | 204 | |input_receiver, output_sender| { |
diff --git a/crates/ra_lsp_server/src/thread_watcher.rs b/crates/ra_lsp_server/src/thread_watcher.rs deleted file mode 100644 index 99825d440..000000000 --- a/crates/ra_lsp_server/src/thread_watcher.rs +++ /dev/null | |||
@@ -1,81 +0,0 @@ | |||
1 | use std::thread; | ||
2 | |||
3 | use crossbeam_channel::{bounded, unbounded, Receiver, Sender}; | ||
4 | use drop_bomb::DropBomb; | ||
5 | use failure::format_err; | ||
6 | |||
7 | use crate::Result; | ||
8 | |||
9 | pub struct Worker<I, O> { | ||
10 | pub inp: Sender<I>, | ||
11 | pub out: Receiver<O>, | ||
12 | } | ||
13 | |||
14 | impl<I, O> Worker<I, O> { | ||
15 | pub fn spawn<F>(name: &'static str, buf: usize, f: F) -> (Self, ThreadWatcher) | ||
16 | where | ||
17 | F: FnOnce(Receiver<I>, Sender<O>) + Send + 'static, | ||
18 | I: Send + 'static, | ||
19 | O: Send + 'static, | ||
20 | { | ||
21 | let (worker, inp_r, out_s) = worker_chan(buf); | ||
22 | let watcher = ThreadWatcher::spawn(name, move || f(inp_r, out_s)); | ||
23 | (worker, watcher) | ||
24 | } | ||
25 | |||
26 | pub fn stop(self) -> Receiver<O> { | ||
27 | self.out | ||
28 | } | ||
29 | |||
30 | pub fn send(&self, item: I) { | ||
31 | self.inp.send(item) | ||
32 | } | ||
33 | } | ||
34 | |||
35 | pub struct ThreadWatcher { | ||
36 | name: &'static str, | ||
37 | thread: thread::JoinHandle<()>, | ||
38 | bomb: DropBomb, | ||
39 | } | ||
40 | |||
41 | impl ThreadWatcher { | ||
42 | fn spawn(name: &'static str, f: impl FnOnce() + Send + 'static) -> ThreadWatcher { | ||
43 | let thread = thread::spawn(f); | ||
44 | ThreadWatcher { | ||
45 | name, | ||
46 | thread, | ||
47 | bomb: DropBomb::new(format!("ThreadWatcher {} was not stopped", name)), | ||
48 | } | ||
49 | } | ||
50 | |||
51 | pub fn stop(mut self) -> Result<()> { | ||
52 | log::info!("waiting for {} to finish ...", self.name); | ||
53 | let name = self.name; | ||
54 | self.bomb.defuse(); | ||
55 | let res = self | ||
56 | .thread | ||
57 | .join() | ||
58 | .map_err(|_| format_err!("ThreadWatcher {} died", name)); | ||
59 | match &res { | ||
60 | Ok(()) => log::info!("... {} terminated with ok", name), | ||
61 | Err(_) => log::error!("... {} terminated with err", name), | ||
62 | } | ||
63 | res | ||
64 | } | ||
65 | } | ||
66 | |||
67 | /// Sets up worker channels in a deadlock-avoind way. | ||
68 | /// If one sets both input and output buffers to a fixed size, | ||
69 | /// a worker might get stuck. | ||
70 | fn worker_chan<I, O>(buf: usize) -> (Worker<I, O>, Receiver<I>, Sender<O>) { | ||
71 | let (input_sender, input_receiver) = bounded::<I>(buf); | ||
72 | let (output_sender, output_receiver) = unbounded::<O>(); | ||
73 | ( | ||
74 | Worker { | ||
75 | inp: input_sender, | ||
76 | out: output_receiver, | ||
77 | }, | ||
78 | input_receiver, | ||
79 | output_sender, | ||
80 | ) | ||
81 | } | ||
diff --git a/crates/ra_lsp_server/src/vfs.rs b/crates/ra_lsp_server/src/vfs.rs index 00ab3e6c3..fcf7693d8 100644 --- a/crates/ra_lsp_server/src/vfs.rs +++ b/crates/ra_lsp_server/src/vfs.rs | |||
@@ -4,8 +4,7 @@ use std::{ | |||
4 | }; | 4 | }; |
5 | 5 | ||
6 | use walkdir::WalkDir; | 6 | use walkdir::WalkDir; |
7 | 7 | use thread_worker::{WorkerHandle, Worker}; | |
8 | use crate::thread_watcher::{ThreadWatcher, Worker}; | ||
9 | 8 | ||
10 | #[derive(Debug)] | 9 | #[derive(Debug)] |
11 | pub struct FileEvent { | 10 | pub struct FileEvent { |
@@ -18,8 +17,8 @@ pub enum FileEventKind { | |||
18 | Add(String), | 17 | Add(String), |
19 | } | 18 | } |
20 | 19 | ||
21 | pub fn roots_loader() -> (Worker<PathBuf, (PathBuf, Vec<FileEvent>)>, ThreadWatcher) { | 20 | pub fn roots_loader() -> (Worker<PathBuf, (PathBuf, Vec<FileEvent>)>, WorkerHandle) { |
22 | Worker::<PathBuf, (PathBuf, Vec<FileEvent>)>::spawn( | 21 | thread_worker::spawn::<PathBuf, (PathBuf, Vec<FileEvent>), _>( |
23 | "roots loader", | 22 | "roots loader", |
24 | 128, | 23 | 128, |
25 | |input_receiver, output_sender| { | 24 | |input_receiver, output_sender| { |
diff --git a/crates/ra_lsp_server/tests/heavy_tests/support.rs b/crates/ra_lsp_server/tests/heavy_tests/support.rs index 4b75be3ee..07a878a26 100644 --- a/crates/ra_lsp_server/tests/heavy_tests/support.rs +++ b/crates/ra_lsp_server/tests/heavy_tests/support.rs | |||
@@ -17,11 +17,11 @@ use languageserver_types::{ | |||
17 | use serde::Serialize; | 17 | use serde::Serialize; |
18 | use serde_json::{to_string_pretty, Value}; | 18 | use serde_json::{to_string_pretty, Value}; |
19 | use tempdir::TempDir; | 19 | use tempdir::TempDir; |
20 | use thread_worker::{WorkerHandle, Worker}; | ||
20 | use test_utils::{parse_fixture, find_mismatch}; | 21 | use test_utils::{parse_fixture, find_mismatch}; |
21 | 22 | ||
22 | use ra_lsp_server::{ | 23 | use ra_lsp_server::{ |
23 | main_loop, req, | 24 | main_loop, req, |
24 | thread_watcher::{ThreadWatcher, Worker}, | ||
25 | }; | 25 | }; |
26 | 26 | ||
27 | pub fn project(fixture: &str) -> Server { | 27 | pub fn project(fixture: &str) -> Server { |
@@ -45,13 +45,13 @@ pub struct Server { | |||
45 | messages: RefCell<Vec<RawMessage>>, | 45 | messages: RefCell<Vec<RawMessage>>, |
46 | dir: TempDir, | 46 | dir: TempDir, |
47 | worker: Option<Worker<RawMessage, RawMessage>>, | 47 | worker: Option<Worker<RawMessage, RawMessage>>, |
48 | watcher: Option<ThreadWatcher>, | 48 | watcher: Option<WorkerHandle>, |
49 | } | 49 | } |
50 | 50 | ||
51 | impl Server { | 51 | impl Server { |
52 | fn new(dir: TempDir, files: Vec<(PathBuf, String)>) -> Server { | 52 | fn new(dir: TempDir, files: Vec<(PathBuf, String)>) -> Server { |
53 | let path = dir.path().to_path_buf(); | 53 | let path = dir.path().to_path_buf(); |
54 | let (worker, watcher) = Worker::<RawMessage, RawMessage>::spawn( | 54 | let (worker, watcher) = thread_worker::spawn::<RawMessage, RawMessage, _>( |
55 | "test server", | 55 | "test server", |
56 | 128, | 56 | 128, |
57 | move |mut msg_receiver, mut msg_sender| { | 57 | move |mut msg_receiver, mut msg_sender| { |