fix deadlock

This commit is contained in:
Aleksey Kladov 2018-09-08 12:08:46 +03:00
parent f48b9d9be7
commit d9ccebd913

View file

@ -8,7 +8,7 @@ use std::{
}; };
use tempdir::TempDir; use tempdir::TempDir;
use crossbeam_channel::{bounded, after, Sender, Receiver}; use crossbeam_channel::{unbounded, after, Sender, Receiver};
use flexi_logger::Logger; use flexi_logger::Logger;
use languageserver_types::{ use languageserver_types::{
Url, Url,
@ -54,7 +54,6 @@ pub fn project(fixture: &str) -> Server {
buf.push('\n'); buf.push('\n');
} }
flush!(); flush!();
Server::new(tmp_dir, paths) Server::new(tmp_dir, paths)
} }
@ -70,8 +69,8 @@ pub struct Server {
impl Server { impl Server {
fn new(dir: TempDir, files: Vec<(PathBuf, String)>) -> Server { fn new(dir: TempDir, files: Vec<(PathBuf, String)>) -> Server {
let path = dir.path().to_path_buf(); let path = dir.path().to_path_buf();
let (client_sender, mut server_receiver) = bounded(1); let (client_sender, mut server_receiver) = unbounded();
let (mut server_sender, client_receiver) = bounded(1); let (mut server_sender, client_receiver) = unbounded();
let server = thread::spawn(move || main_loop(true, path, &mut server_receiver, &mut server_sender)); let server = thread::spawn(move || main_loop(true, path, &mut server_receiver, &mut server_sender));
let res = Server { let res = Server {
req_id: Cell::new(1), req_id: Cell::new(1),
@ -81,6 +80,7 @@ impl Server {
receiver: client_receiver, receiver: client_receiver,
server: Some(server), server: Some(server),
}; };
for (path, text) in files { for (path, text) in files {
res.send_notification(RawNotification::new::<DidOpenTextDocument>( res.send_notification(RawNotification::new::<DidOpenTextDocument>(
&DidOpenTextDocumentParams { &DidOpenTextDocumentParams {
@ -179,12 +179,8 @@ impl Server {
} }
} }
fn recv(&self) -> Option<RawMessage> { fn recv(&self) -> Option<RawMessage> {
let timeout = Duration::from_secs(5); recv_timeout(&self.receiver)
let msg = select! { .map(|msg| {
recv(&self.receiver, msg) => msg,
recv(after(timeout)) => panic!("timed out"),
};
msg.map(|msg| {
self.messages.borrow_mut().push(msg.clone()); self.messages.borrow_mut().push(msg.clone());
msg msg
}) })
@ -201,7 +197,7 @@ impl Drop for Server {
{ {
self.send_request::<Shutdown>(666, ()); self.send_request::<Shutdown>(666, ());
drop(self.sender.take().unwrap()); drop(self.sender.take().unwrap());
while let Some(msg) = self.receiver.recv() { while let Some(msg) = recv_timeout(&self.receiver) {
drop(msg); drop(msg);
} }
} }
@ -210,3 +206,11 @@ impl Drop for Server {
.join().unwrap().unwrap(); .join().unwrap().unwrap();
} }
} }
fn recv_timeout(receiver: &Receiver<RawMessage>) -> Option<RawMessage> {
let timeout = Duration::from_secs(5);
select! {
recv(receiver, msg) => msg,
recv(after(timeout)) => panic!("timed out"),
}
}