瀏覽代碼

fix(core): command API emitting terminated event before stdout finish (#1471)

Lucas Fernandes Nogueira 4 年之前
父節點
當前提交
86f62d3c6e
共有 2 個文件被更改,包括 30 次插入21 次删除
  1. 29 20
      core/tauri/src/api/command.rs
  2. 1 1
      core/tauri/src/api/mod.rs

+ 29 - 20
core/tauri/src/api/command.rs

@@ -16,7 +16,7 @@ use std::os::windows::process::CommandExt;
 #[cfg(windows)]
 const CREATE_NO_WINDOW: u32 = 0x0800_0000;
 
-use crate::api::private::async_runtime::{channel, spawn, Receiver};
+use crate::api::private::async_runtime::{channel, spawn, Receiver, RwLock};
 use os_pipe::{pipe, PipeWriter};
 use serde::Serialize;
 use shared_child::SharedChild;
@@ -131,28 +131,14 @@ impl Command {
     let shared_child = SharedChild::spawn(&mut command)?;
     let child = Arc::new(shared_child);
     let child_ = child.clone();
+    let guard = Arc::new(RwLock::new(()));
 
     let (tx, rx) = channel(1);
-    let tx_ = tx.clone();
-    spawn(async move {
-      let _ = match child_.wait() {
-        Ok(status) => {
-          tx_
-            .send(CommandEvent::Terminated(TerminatedPayload {
-              code: status.code(),
-              #[cfg(windows)]
-              signal: None,
-              #[cfg(unix)]
-              signal: status.signal(),
-            }))
-            .await
-        }
-        Err(e) => tx_.send(CommandEvent::Error(e.to_string())).await,
-      };
-    });
 
     let tx_ = tx.clone();
+    let guard_ = guard.clone();
     spawn(async move {
+      let _lock = guard_.read().await;
       let reader = BufReader::new(stdout_reader);
       for line in reader.lines() {
         let _ = match line {
@@ -162,16 +148,39 @@ impl Command {
       }
     });
 
+    let tx_ = tx.clone();
+    let guard_ = guard.clone();
     spawn(async move {
+      let _lock = guard_.read().await;
       let reader = BufReader::new(stderr_reader);
       for line in reader.lines() {
         let _ = match line {
-          Ok(line) => tx.send(CommandEvent::Stderr(line)).await,
-          Err(e) => tx.send(CommandEvent::Error(e.to_string())).await,
+          Ok(line) => tx_.send(CommandEvent::Stderr(line)).await,
+          Err(e) => tx_.send(CommandEvent::Error(e.to_string())).await,
         };
       }
     });
 
+    spawn(async move {
+      let _ = match child_.wait() {
+        Ok(status) => {
+          guard.write().await;
+          tx.send(CommandEvent::Terminated(TerminatedPayload {
+            code: status.code(),
+            #[cfg(windows)]
+            signal: None,
+            #[cfg(unix)]
+            signal: status.signal(),
+          }))
+          .await
+        }
+        Err(e) => {
+          guard.write().await;
+          tx.send(CommandEvent::Error(e.to_string())).await
+        }
+      };
+    });
+
     Ok((
       rx,
       CommandChild {

+ 1 - 1
core/tauri/src/api/mod.rs

@@ -74,7 +74,7 @@ pub mod private {
     use tokio::runtime::Runtime;
     pub use tokio::sync::{
       mpsc::{channel, Receiver, Sender},
-      Mutex,
+      Mutex, RwLock,
     };
 
     use std::future::Future;