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

This commit is contained in:
Lucas Fernandes Nogueira 2021-04-13 10:56:09 -03:00 committed by GitHub
parent b359444317
commit 86f62d3c6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 30 additions and 21 deletions

View File

@ -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 {

View File

@ -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;