]> git.lizzy.rs Git - rust.git/commitdiff
Remove proc macro management thread
authorJonas Schievink <jonasschievink@gmail.com>
Thu, 8 Jul 2021 14:40:14 +0000 (16:40 +0200)
committerJonas Schievink <jonasschievink@gmail.com>
Thu, 8 Jul 2021 14:43:39 +0000 (16:43 +0200)
crates/proc_macro_api/src/lib.rs
crates/proc_macro_api/src/process.rs
crates/stdx/src/lib.rs

index 654bd9943ebcd4abeefb94d611da20b89c979ffa..5054bc7643da9c2f1e162b18e035dda173ddfebc 100644 (file)
@@ -20,7 +20,7 @@
 
 use tt::{SmolStr, Subtree};
 
-use crate::process::{ProcMacroProcessSrv, ProcMacroProcessThread};
+use crate::process::ProcMacroProcessSrv;
 
 pub use rpc::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask, ProcMacroKind};
 pub use version::{read_dylib_info, RustCInfo};
@@ -64,16 +64,16 @@ fn expand(
 #[derive(Debug)]
 pub struct ProcMacroClient {
     process: Arc<ProcMacroProcessSrv>,
-    thread: ProcMacroProcessThread,
 }
 
 impl ProcMacroClient {
+    /// Spawns an external process as the proc macro server and returns a client connected to it.
     pub fn extern_process(
         process_path: PathBuf,
         args: impl IntoIterator<Item = impl AsRef<OsStr>>,
     ) -> io::Result<ProcMacroClient> {
-        let (thread, process) = ProcMacroProcessSrv::run(process_path, args)?;
-        Ok(ProcMacroClient { process: Arc::new(process), thread })
+        let process = ProcMacroProcessSrv::run(process_path, args)?;
+        Ok(ProcMacroClient { process: Arc::new(process) })
     }
 
     pub fn by_dylib_path(&self, dylib_path: &Path) -> Vec<ProcMacro> {
index 91d6a3811be22f59cb8ee90ad75527cb4037bad7..592c1282c0bce575400ac8236cb141f693cff8c4 100644 (file)
@@ -3,13 +3,13 @@
 use std::{
     convert::{TryFrom, TryInto},
     ffi::{OsStr, OsString},
+    fmt,
     io::{self, BufRead, BufReader, Write},
     path::{Path, PathBuf},
-    process::{Child, Command, Stdio},
-    sync::{Arc, Weak},
+    process::{Child, ChildStdin, ChildStdout, Command, Stdio},
+    sync::Mutex,
 };
 
-use crossbeam_channel::{bounded, Receiver, Sender};
 use stdx::JodChild;
 
 use crate::{
     rpc::{ListMacrosResult, ListMacrosTask, ProcMacroKind},
 };
 
-#[derive(Debug, Default)]
 pub(crate) struct ProcMacroProcessSrv {
-    inner: Weak<Sender<Task>>,
+    process: Mutex<Process>,
+    stdio: Mutex<(ChildStdin, BufReader<ChildStdout>)>,
 }
 
-#[derive(Debug)]
-pub(crate) struct ProcMacroProcessThread {
-    // XXX: drop order is significant
-    sender: Arc<Sender<Task>>,
-    handle: jod_thread::JoinHandle<()>,
+impl fmt::Debug for ProcMacroProcessSrv {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("ProcMacroProcessSrv").field("process", &self.process).finish()
+    }
 }
 
 impl ProcMacroProcessSrv {
     pub(crate) fn run(
         process_path: PathBuf,
         args: impl IntoIterator<Item = impl AsRef<OsStr>>,
-    ) -> io::Result<(ProcMacroProcessThread, ProcMacroProcessSrv)> {
-        let process = Process::run(process_path, args)?;
-
-        let (task_tx, task_rx) = bounded(0);
-        let handle = jod_thread::Builder::new()
-            .name("ProcMacroClient".to_owned())
-            .spawn(move || {
-                client_loop(task_rx, process);
-            })
-            .expect("failed to spawn thread");
-
-        let task_tx = Arc::new(task_tx);
-        let srv = ProcMacroProcessSrv { inner: Arc::downgrade(&task_tx) };
-        let thread = ProcMacroProcessThread { handle, sender: task_tx };
-
-        Ok((thread, srv))
+    ) -> io::Result<ProcMacroProcessSrv> {
+        let mut process = Process::run(process_path, args)?;
+        let (stdin, stdout) = process.stdio().expect("couldn't access child stdio");
+
+        let srv = ProcMacroProcessSrv {
+            process: Mutex::new(process),
+            stdio: Mutex::new((stdin, stdout)),
+        };
+
+        Ok(srv)
     }
 
     pub(crate) fn find_proc_macros(
@@ -65,38 +58,15 @@ pub(crate) fn send_task<R>(&self, req: Request) -> Result<R, tt::ExpansionError>
     where
         R: TryFrom<Response, Error = &'static str>,
     {
-        let (result_tx, result_rx) = bounded(0);
-        let sender = match self.inner.upgrade() {
-            None => return Err(tt::ExpansionError::Unknown("proc macro process is closed".into())),
-            Some(it) => it,
-        };
-        sender
-            .send(Task { req, result_tx })
-            .map_err(|_| tt::ExpansionError::Unknown("proc macro server crashed".into()))?;
+        let mut guard = self.stdio.lock().unwrap_or_else(|e| e.into_inner());
+        let stdio = &mut *guard;
+        let (stdin, stdout) = (&mut stdio.0, &mut stdio.1);
 
-        let res = result_rx
-            .recv()
-            .map_err(|_| tt::ExpansionError::Unknown("proc macro server crashed".into()))?;
-
-        match res {
-            Some(Response::Error(err)) => Err(tt::ExpansionError::ExpansionError(err.message)),
-            Some(res) => Ok(res.try_into().map_err(|err| {
-                tt::ExpansionError::Unknown(format!("Fail to get response, reason : {:#?} ", err))
-            })?),
-            None => Err(tt::ExpansionError::Unknown("Empty result".into())),
-        }
-    }
-}
-
-fn client_loop(task_rx: Receiver<Task>, mut process: Process) {
-    let (mut stdin, mut stdout) = process.stdio().expect("couldn't access child stdio");
-
-    let mut buf = String::new();
-
-    for Task { req, result_tx } in task_rx {
-        match send_request(&mut stdin, &mut stdout, req, &mut buf) {
-            Ok(res) => result_tx.send(res).unwrap(),
+        let mut buf = String::new();
+        let res = match send_request(stdin, stdout, req, &mut buf) {
+            Ok(res) => res,
             Err(err) => {
+                let mut process = self.process.lock().unwrap_or_else(|e| e.into_inner());
                 log::error!(
                     "proc macro server crashed, server process state: {:?}, server request error: {:?}",
                     process.child.try_wait(),
@@ -106,19 +76,21 @@ fn client_loop(task_rx: Receiver<Task>, mut process: Process) {
                     code: ErrorCode::ServerErrorEnd,
                     message: "proc macro server crashed".into(),
                 });
-                result_tx.send(res.into()).unwrap();
-                // Exit the thread.
-                break;
+                Some(res)
             }
+        };
+
+        match res {
+            Some(Response::Error(err)) => Err(tt::ExpansionError::ExpansionError(err.message)),
+            Some(res) => Ok(res.try_into().map_err(|err| {
+                tt::ExpansionError::Unknown(format!("Fail to get response, reason : {:#?} ", err))
+            })?),
+            None => Err(tt::ExpansionError::Unknown("Empty result".into())),
         }
     }
 }
 
-struct Task {
-    req: Request,
-    result_tx: Sender<Option<Response>>,
-}
-
+#[derive(Debug)]
 struct Process {
     child: JodChild,
 }
@@ -133,7 +105,7 @@ fn run(
         Ok(Process { child })
     }
 
-    fn stdio(&mut self) -> Option<(impl Write, impl BufRead)> {
+    fn stdio(&mut self) -> Option<(ChildStdin, BufReader<ChildStdout>)> {
         let stdin = self.child.stdin.take()?;
         let stdout = self.child.stdout.take()?;
         let read = BufReader::new(stdout);
index 2963484faefc1e95c2d84732afb7e6ede99f5732..e83d5db437d1d218d5fe3c3696e23790366b9de1 100644 (file)
@@ -111,6 +111,7 @@ fn drop(&mut self) {
 }
 
 #[cfg_attr(not(target_arch = "wasm32"), repr(transparent))]
+#[derive(Debug)]
 pub struct JodChild(pub std::process::Child);
 
 impl ops::Deref for JodChild {