Skip to content

Commit

Permalink
fix(core): command events not firing consistently (#2082)
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasfernog committed Jun 27, 2021
1 parent bd038b5 commit 8c13344
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 39 deletions.
5 changes: 5 additions & 0 deletions .changes/fix-command-event-channel.md
@@ -0,0 +1,5 @@
---
"tauri": patch
---

Fixes `api::process::Command` events not firing consistently.
74 changes: 38 additions & 36 deletions core/tauri/src/api/process/command.rs
Expand Up @@ -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)]
Expand All @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
5 changes: 2 additions & 3 deletions core/tauri/src/endpoints/shell.rs
Expand Up @@ -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);
}
Expand Down

0 comments on commit 8c13344

Please sign in to comment.