mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-04-01 10:01:07 +02:00
fix(core): command events not firing consistently (#2082)
This commit is contained in:
committed by
GitHub
parent
bd038b5f5d
commit
8c13344f8f
5
.changes/fix-command-event-channel.md
Normal file
5
.changes/fix-command-event-channel.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tauri": patch
|
||||
---
|
||||
|
||||
Fixes `api::process::Command` events not firing consistently.
|
||||
@@ -7,7 +7,8 @@ use std::{
|
||||
io::{BufRead, BufReader, Write},
|
||||
path::PathBuf,
|
||||
process::{Command as StdCommand, Stdio},
|
||||
sync::{Arc, Mutex},
|
||||
sync::{Arc, Mutex, RwLock},
|
||||
thread::spawn,
|
||||
};
|
||||
|
||||
#[cfg(unix)]
|
||||
@@ -18,8 +19,7 @@ use std::os::windows::process::CommandExt;
|
||||
#[cfg(windows)]
|
||||
const CREATE_NO_WINDOW: u32 = 0x0800_0000;
|
||||
|
||||
use crate::async_runtime::{channel, spawn, Receiver, RwLock};
|
||||
use futures::{future, FutureExt};
|
||||
use crate::async_runtime::{channel, spawn as spawn_task, Receiver};
|
||||
use os_pipe::{pipe, PipeWriter};
|
||||
use serde::Serialize;
|
||||
use shared_child::SharedChild;
|
||||
@@ -243,56 +243,58 @@ impl Command {
|
||||
|
||||
let tx_ = tx.clone();
|
||||
let guard_ = guard.clone();
|
||||
let stdout_task = async move {
|
||||
let _lock = guard_.read().await;
|
||||
spawn(move || {
|
||||
let _lock = guard_.read().unwrap();
|
||||
let reader = BufReader::new(stdout_reader);
|
||||
for line in reader.lines() {
|
||||
let _ = match line {
|
||||
Ok(line) => tx_.send(CommandEvent::Stdout(line)).await,
|
||||
Err(e) => tx_.send(CommandEvent::Error(e.to_string())).await,
|
||||
};
|
||||
let tx_ = tx_.clone();
|
||||
spawn_task(async move {
|
||||
let _ = match line {
|
||||
Ok(line) => tx_.send(CommandEvent::Stdout(line)).await,
|
||||
Err(e) => tx_.send(CommandEvent::Error(e.to_string())).await,
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
let tx_ = tx.clone();
|
||||
let guard_ = guard.clone();
|
||||
let stderr_task = async move {
|
||||
let _lock = guard_.read().await;
|
||||
spawn(move || {
|
||||
let _lock = guard_.read().unwrap();
|
||||
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,
|
||||
};
|
||||
let tx_ = tx_.clone();
|
||||
spawn_task(async move {
|
||||
let _ = match line {
|
||||
Ok(line) => tx_.send(CommandEvent::Stderr(line)).await,
|
||||
Err(e) => tx_.send(CommandEvent::Error(e.to_string())).await,
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
let terminated_task = async move {
|
||||
spawn(move || {
|
||||
let _ = match child_.wait() {
|
||||
Ok(status) => {
|
||||
guard.write().await;
|
||||
let _l = guard.write().unwrap();
|
||||
commands().lock().unwrap().remove(&child_.id());
|
||||
tx.send(CommandEvent::Terminated(TerminatedPayload {
|
||||
code: status.code(),
|
||||
#[cfg(windows)]
|
||||
signal: None,
|
||||
#[cfg(unix)]
|
||||
signal: status.signal(),
|
||||
}))
|
||||
.await
|
||||
spawn_task(async move {
|
||||
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
|
||||
let _l = guard.write().unwrap();
|
||||
spawn_task(async move { tx.send(CommandEvent::Error(e.to_string())).await });
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
spawn(future::join_all(vec![
|
||||
stdout_task.boxed(),
|
||||
stderr_task.boxed(),
|
||||
terminated_task.boxed(),
|
||||
]));
|
||||
});
|
||||
|
||||
Ok((
|
||||
rx,
|
||||
|
||||
@@ -102,9 +102,8 @@ impl Cmd {
|
||||
let pid = child.pid();
|
||||
command_childs().lock().unwrap().insert(pid, child);
|
||||
|
||||
// TODO: for some reason using `crate::async_runtime::spawn` and `rx.recv().await` doesn't work here, see issue #1935
|
||||
std::thread::spawn(move || {
|
||||
while let Some(event) = rx.blocking_recv() {
|
||||
crate::async_runtime::spawn(async move {
|
||||
while let Some(event) = rx.recv().await {
|
||||
if matches!(event, crate::api::process::CommandEvent::Terminated(_)) {
|
||||
command_childs().lock().unwrap().remove(&pid);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user