diff --git a/package.json b/package.json index 09cdd1c..1e24380 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "iccery", "private": true, - "version": "0.1.15", + "version": "0.1.16", "type": "module", "scripts": { "tauri": "tauri" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index dc5eb5a..a75f5b2 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "iccery" -version = "0.1.15" +version = "0.1.16" description = "Modern Printer Profiling UI frontend for ArgyllCMS" authors = ["Gordon"] edition = "2021" diff --git a/src-tauri/src/process_manager.rs b/src-tauri/src/process_manager.rs index 72f823f..ed31858 100644 --- a/src-tauri/src/process_manager.rs +++ b/src-tauri/src/process_manager.rs @@ -1,29 +1,32 @@ use std::collections::HashMap; use std::process::Stdio; +use std::sync::Arc; +use tauri::AppHandle; use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader}; use tokio::process::{Child, Command}; use tokio::sync::Mutex; -use tauri::AppHandle; - -#[cfg(windows)] -use std::os::windows::process::CommandExt; use crate::events::{emit_error, emit_stderr, emit_stdout}; -use std::sync::Arc; - pub struct ProcessManager { - processes: Mutex>>>, + processes: Arc>>>>, } impl ProcessManager { pub fn new() -> Self { Self { - processes: Mutex::new(HashMap::new()), + processes: Arc::new(Mutex::new(HashMap::new())), } } - pub async fn spawn(&self, app: AppHandle, id: String, binary: String, args: Vec, cwd: Option) -> Result<(), String> { + pub async fn spawn( + &self, + app: AppHandle, + id: String, + binary: String, + args: Vec, + cwd: Option, + ) -> Result<(), String> { let mut command = Command::new(&binary); command.args(args); if let Some(dir) = cwd { @@ -43,7 +46,7 @@ impl ProcessManager { Ok(mut child) => { let stdout = child.stdout.take().expect("Failed to open stdout"); let stderr = child.stderr.take().expect("Failed to open stderr"); - + let id_clone = id.clone(); let app_clone = app.clone(); tokio::spawn(async move { @@ -67,24 +70,34 @@ impl ProcessManager { emit_stderr(&app_clone2, &id_clone2, line); } }); - + let child_arc = Arc::new(Mutex::new(child)); - let mut processes = self.processes.lock().await; - processes.insert(id.clone(), child_arc.clone()); - + { + let mut processes = self.processes.lock().await; + processes.insert(id.clone(), child_arc.clone()); + } + let id_clone_exit = id.clone(); let app_clone_exit = app.clone(); + let processes_clone = self.processes.clone(); tokio::spawn(async move { - loop { - tokio::time::sleep(std::time::Duration::from_millis(100)).await; + let exit_code = { let mut c = child_arc.lock().await; - if let Ok(Some(status)) = c.try_wait() { - crate::events::emit_exit(&app_clone_exit, &id_clone_exit, status.code().unwrap_or(1)); - break; + match c.wait().await { + Ok(status) => status.code().unwrap_or(0), + Err(_) => 1, } + }; + + // Reap child from process manager map upon exit + { + let mut processes = processes_clone.lock().await; + processes.remove(&id_clone_exit); } + + crate::events::emit_exit(&app_clone_exit, &id_clone_exit, exit_code); }); - + Ok(()) } Err(e) => { diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 8b18854..abe90a7 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "ICCery", - "version": "0.1.15", + "version": "0.1.16", "identifier": "com.gronod.iccery", "build": { "frontendDist": "../src"