mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-25 20:43:21 +00:00
Use automatic thread joining for cargo-watch
This commit is contained in:
parent
8bea5ace7e
commit
f7df0b56a7
3 changed files with 10 additions and 40 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -893,6 +893,7 @@ dependencies = [
|
||||||
"cargo_metadata",
|
"cargo_metadata",
|
||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
"insta",
|
"insta",
|
||||||
|
"jod-thread",
|
||||||
"log",
|
"log",
|
||||||
"lsp-types",
|
"lsp-types",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
|
|
@ -10,6 +10,7 @@ lsp-types = { version = "0.73.0", features = ["proposed"] }
|
||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
cargo_metadata = "0.9.1"
|
cargo_metadata = "0.9.1"
|
||||||
serde_json = "1.0.48"
|
serde_json = "1.0.48"
|
||||||
|
jod-thread = "0.1.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
insta = "0.15.0"
|
insta = "0.15.0"
|
||||||
|
|
|
@ -12,7 +12,6 @@ use std::{
|
||||||
io::{BufRead, BufReader},
|
io::{BufRead, BufReader},
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
process::{Command, Stdio},
|
process::{Command, Stdio},
|
||||||
thread::JoinHandle,
|
|
||||||
time::Instant,
|
time::Instant,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -37,8 +36,9 @@ pub struct CheckOptions {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CheckWatcher {
|
pub struct CheckWatcher {
|
||||||
pub task_recv: Receiver<CheckTask>,
|
pub task_recv: Receiver<CheckTask>,
|
||||||
|
// XXX: drop order is significant
|
||||||
cmd_send: Option<Sender<CheckCommand>>,
|
cmd_send: Option<Sender<CheckCommand>>,
|
||||||
handle: Option<JoinHandle<()>>,
|
handle: Option<jod_thread::JoinHandle<()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CheckWatcher {
|
impl CheckWatcher {
|
||||||
|
@ -47,7 +47,7 @@ impl CheckWatcher {
|
||||||
|
|
||||||
let (task_send, task_recv) = unbounded::<CheckTask>();
|
let (task_send, task_recv) = unbounded::<CheckTask>();
|
||||||
let (cmd_send, cmd_recv) = unbounded::<CheckCommand>();
|
let (cmd_send, cmd_recv) = unbounded::<CheckCommand>();
|
||||||
let handle = std::thread::spawn(move || {
|
let handle = jod_thread::spawn(move || {
|
||||||
let mut check = CheckWatcherThread::new(options, workspace_root);
|
let mut check = CheckWatcherThread::new(options, workspace_root);
|
||||||
check.run(&task_send, &cmd_recv);
|
check.run(&task_send, &cmd_recv);
|
||||||
});
|
});
|
||||||
|
@ -67,22 +67,6 @@ impl CheckWatcher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::Drop for CheckWatcher {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
if let Some(handle) = self.handle.take() {
|
|
||||||
// Take the sender out of the option
|
|
||||||
let cmd_send = self.cmd_send.take();
|
|
||||||
|
|
||||||
// Dropping the sender finishes the thread loop
|
|
||||||
drop(cmd_send);
|
|
||||||
|
|
||||||
// Join the thread, it should finish shortly. We don't really care
|
|
||||||
// whether it panicked, so it is safe to ignore the result
|
|
||||||
let _ = handle.join();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum CheckTask {
|
pub enum CheckTask {
|
||||||
/// Request a clearing of all cached diagnostics from the check watcher
|
/// Request a clearing of all cached diagnostics from the check watcher
|
||||||
|
@ -237,8 +221,9 @@ pub struct DiagnosticWithFixes {
|
||||||
/// The correct way to dispose of the thread is to drop it, on which the
|
/// The correct way to dispose of the thread is to drop it, on which the
|
||||||
/// sub-process will be killed, and the thread will be joined.
|
/// sub-process will be killed, and the thread will be joined.
|
||||||
struct WatchThread {
|
struct WatchThread {
|
||||||
handle: Option<JoinHandle<()>>,
|
// XXX: drop order is significant
|
||||||
message_recv: Receiver<CheckEvent>,
|
message_recv: Receiver<CheckEvent>,
|
||||||
|
_handle: Option<jod_thread::JoinHandle<()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum CheckEvent {
|
enum CheckEvent {
|
||||||
|
@ -333,7 +318,7 @@ pub fn run_cargo(
|
||||||
|
|
||||||
impl WatchThread {
|
impl WatchThread {
|
||||||
fn dummy() -> WatchThread {
|
fn dummy() -> WatchThread {
|
||||||
WatchThread { handle: None, message_recv: never() }
|
WatchThread { message_recv: never(), _handle: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new(options: &CheckOptions, workspace_root: &Path) -> WatchThread {
|
fn new(options: &CheckOptions, workspace_root: &Path) -> WatchThread {
|
||||||
|
@ -352,7 +337,7 @@ impl WatchThread {
|
||||||
let (message_send, message_recv) = unbounded();
|
let (message_send, message_recv) = unbounded();
|
||||||
let workspace_root = workspace_root.to_owned();
|
let workspace_root = workspace_root.to_owned();
|
||||||
let handle = if options.enable {
|
let handle = if options.enable {
|
||||||
Some(std::thread::spawn(move || {
|
Some(jod_thread::spawn(move || {
|
||||||
// If we trigger an error here, we will do so in the loop instead,
|
// If we trigger an error here, we will do so in the loop instead,
|
||||||
// which will break out of the loop, and continue the shutdown
|
// which will break out of the loop, and continue the shutdown
|
||||||
let _ = message_send.send(CheckEvent::Begin);
|
let _ = message_send.send(CheckEvent::Begin);
|
||||||
|
@ -383,23 +368,6 @@ impl WatchThread {
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
WatchThread { handle, message_recv }
|
WatchThread { message_recv, _handle: handle }
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::ops::Drop for WatchThread {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
if let Some(handle) = self.handle.take() {
|
|
||||||
// Replace our reciever with dummy one, so we can drop and close the
|
|
||||||
// one actually communicating with the thread
|
|
||||||
let recv = std::mem::replace(&mut self.message_recv, never());
|
|
||||||
|
|
||||||
// Dropping the original reciever initiates thread sub-process shutdown
|
|
||||||
drop(recv);
|
|
||||||
|
|
||||||
// Join the thread, it should finish shortly. We don't really care
|
|
||||||
// whether it panicked, so it is safe to ignore the result
|
|
||||||
let _ = handle.join();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue