aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_proc_macro
diff options
context:
space:
mode:
authorEdwin Cheng <[email protected]>2020-03-27 04:55:58 +0000
committerEdwin Cheng <[email protected]>2020-03-31 15:20:18 +0100
commit55061b489fc36b17819c1a18f89c36078763cdfa (patch)
treee9f6cef477150124196425c5acd6582f5f4497c7 /crates/ra_proc_macro
parent1b8a26653f9d8734767a40af576223e267d51d6d (diff)
Improve shutdown process
Diffstat (limited to 'crates/ra_proc_macro')
-rw-r--r--crates/ra_proc_macro/src/lib.rs16
-rw-r--r--crates/ra_proc_macro/src/process.rs57
2 files changed, 54 insertions, 19 deletions
diff --git a/crates/ra_proc_macro/src/lib.rs b/crates/ra_proc_macro/src/lib.rs
index a0a478dc8..51fbb046a 100644
--- a/crates/ra_proc_macro/src/lib.rs
+++ b/crates/ra_proc_macro/src/lib.rs
@@ -9,7 +9,7 @@ mod rpc;
9mod process; 9mod process;
10pub mod msg; 10pub mod msg;
11 11
12use process::ProcMacroProcessSrv; 12use process::{ProcMacroProcessSrv, ProcMacroProcessThread};
13use ra_tt::{SmolStr, Subtree}; 13use ra_tt::{SmolStr, Subtree};
14use rpc::ProcMacroKind; 14use rpc::ProcMacroKind;
15use std::{ 15use std::{
@@ -45,21 +45,23 @@ impl ra_tt::TokenExpander for ProcMacroProcessExpander {
45 } 45 }
46} 46}
47 47
48#[derive(Debug, Clone)] 48#[derive(Debug)]
49enum ProcMacroClientKind { 49enum ProcMacroClientKind {
50 Process { process: Arc<ProcMacroProcessSrv> }, 50 Process { process: Arc<ProcMacroProcessSrv>, thread: ProcMacroProcessThread },
51 Dummy, 51 Dummy,
52} 52}
53 53
54#[derive(Debug, Clone)] 54#[derive(Debug)]
55pub struct ProcMacroClient { 55pub struct ProcMacroClient {
56 kind: ProcMacroClientKind, 56 kind: ProcMacroClientKind,
57} 57}
58 58
59impl ProcMacroClient { 59impl ProcMacroClient {
60 pub fn extern_process(process_path: &Path) -> Result<ProcMacroClient, std::io::Error> { 60 pub fn extern_process(process_path: &Path) -> Result<ProcMacroClient, std::io::Error> {
61 let process = ProcMacroProcessSrv::run(process_path)?; 61 let (thread, process) = ProcMacroProcessSrv::run(process_path)?;
62 Ok(ProcMacroClient { kind: ProcMacroClientKind::Process { process: Arc::new(process) } }) 62 Ok(ProcMacroClient {
63 kind: ProcMacroClientKind::Process { process: Arc::new(process), thread },
64 })
63 } 65 }
64 66
65 pub fn dummy() -> ProcMacroClient { 67 pub fn dummy() -> ProcMacroClient {
@@ -72,7 +74,7 @@ impl ProcMacroClient {
72 ) -> Vec<(SmolStr, Arc<dyn ra_tt::TokenExpander>)> { 74 ) -> Vec<(SmolStr, Arc<dyn ra_tt::TokenExpander>)> {
73 match &self.kind { 75 match &self.kind {
74 ProcMacroClientKind::Dummy => vec![], 76 ProcMacroClientKind::Dummy => vec![],
75 ProcMacroClientKind::Process { process } => { 77 ProcMacroClientKind::Process { process, .. } => {
76 let macros = match process.find_proc_macros(dylib_path) { 78 let macros = match process.find_proc_macros(dylib_path) {
77 Err(err) => { 79 Err(err) => {
78 eprintln!("Fail to find proc macro. Error: {:#?}", err); 80 eprintln!("Fail to find proc macro. Error: {:#?}", err);
diff --git a/crates/ra_proc_macro/src/process.rs b/crates/ra_proc_macro/src/process.rs
index 6a3fe2e20..d028b365c 100644
--- a/crates/ra_proc_macro/src/process.rs
+++ b/crates/ra_proc_macro/src/process.rs
@@ -11,7 +11,7 @@ use std::{
11 io::{self, Write}, 11 io::{self, Write},
12 path::{Path, PathBuf}, 12 path::{Path, PathBuf},
13 process::{Child, Command, Stdio}, 13 process::{Child, Command, Stdio},
14 thread::spawn, 14 thread::{spawn, JoinHandle},
15}; 15};
16 16
17#[derive(Debug, Default)] 17#[derive(Debug, Default)]
@@ -19,9 +19,15 @@ pub(crate) struct ProcMacroProcessSrv {
19 inner: Option<Handle>, 19 inner: Option<Handle>,
20} 20}
21 21
22struct Task { 22#[derive(Debug)]
23 req: Message, 23pub(crate) struct ProcMacroProcessThread {
24 result_tx: Sender<Message>, 24 handle: Option<JoinHandle<()>>,
25 sender: Sender<Task>,
26}
27
28enum Task {
29 Request { req: Message, result_tx: Sender<Message> },
30 Close,
25} 31}
26 32
27#[derive(Debug)] 33#[derive(Debug)]
@@ -60,16 +66,33 @@ impl Process {
60 } 66 }
61} 67}
62 68
69impl std::ops::Drop for ProcMacroProcessThread {
70 fn drop(&mut self) {
71 if let Some(handle) = self.handle.take() {
72 let _ = self.sender.send(Task::Close);
73
74 // Join the thread, it should finish shortly. We don't really care
75 // whether it panicked, so it is safe to ignore the result
76 let _ = handle.join();
77 }
78 }
79}
80
63impl ProcMacroProcessSrv { 81impl ProcMacroProcessSrv {
64 pub fn run(process_path: &Path) -> Result<ProcMacroProcessSrv, io::Error> { 82 pub fn run(
83 process_path: &Path,
84 ) -> Result<(ProcMacroProcessThread, ProcMacroProcessSrv), io::Error> {
65 let process = Process::run(process_path)?; 85 let process = Process::run(process_path)?;
66 86
67 let (task_tx, task_rx) = bounded(0); 87 let (task_tx, task_rx) = bounded(0);
68 88 let handle = spawn(move || {
69 let _ = spawn(move || {
70 client_loop(task_rx, process); 89 client_loop(task_rx, process);
71 }); 90 });
72 Ok(ProcMacroProcessSrv { inner: Some(Handle { sender: task_tx }) }) 91
92 let srv = ProcMacroProcessSrv { inner: Some(Handle { sender: task_tx.clone() }) };
93 let thread = ProcMacroProcessThread { handle: Some(handle), sender: task_tx };
94
95 Ok((thread, srv))
73 } 96 }
74 97
75 pub fn find_proc_macros( 98 pub fn find_proc_macros(
@@ -117,7 +140,12 @@ impl ProcMacroProcessSrv {
117 140
118 let (result_tx, result_rx) = bounded(0); 141 let (result_tx, result_rx) = bounded(0);
119 142
120 handle.sender.send(Task { req: req.into(), result_tx }).unwrap(); 143 handle.sender.send(Task::Request { req: req.into(), result_tx }).map_err(|err| {
144 ra_tt::ExpansionError::Unknown(format!(
145 "Fail to send task in channel, reason : {:#?} ",
146 err
147 ))
148 })?;
121 let response = result_rx.recv().unwrap(); 149 let response = result_rx.recv().unwrap();
122 150
123 match response { 151 match response {
@@ -155,7 +183,12 @@ fn client_loop(task_rx: Receiver<Task>, mut process: Process) {
155 Err(_) => break, 183 Err(_) => break,
156 }; 184 };
157 185
158 let res = match send_message(&mut stdin, &mut stdout, task.req) { 186 let (req, result_tx) = match task {
187 Task::Request { req, result_tx } => (req, result_tx),
188 Task::Close => break,
189 };
190
191 let res = match send_message(&mut stdin, &mut stdout, req) {
159 Ok(res) => res, 192 Ok(res) => res,
160 Err(_err) => { 193 Err(_err) => {
161 let res = Response { 194 let res = Response {
@@ -167,7 +200,7 @@ fn client_loop(task_rx: Receiver<Task>, mut process: Process) {
167 data: None, 200 data: None,
168 }), 201 }),
169 }; 202 };
170 if task.result_tx.send(res.into()).is_err() { 203 if result_tx.send(res.into()).is_err() {
171 break; 204 break;
172 } 205 }
173 // Restart the process 206 // Restart the process
@@ -185,7 +218,7 @@ fn client_loop(task_rx: Receiver<Task>, mut process: Process) {
185 }; 218 };
186 219
187 if let Some(res) = res { 220 if let Some(res) = res {
188 if task.result_tx.send(res).is_err() { 221 if result_tx.send(res).is_err() {
189 break; 222 break;
190 } 223 }
191 } 224 }