fix(process_manager): await child exit and reap process handles (v0.1.16) #77
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "iccery",
|
"name": "iccery",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"tauri": "tauri"
|
"tauri": "tauri"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "iccery"
|
name = "iccery"
|
||||||
version = "0.1.15"
|
version = "0.1.16"
|
||||||
description = "Modern Printer Profiling UI frontend for ArgyllCMS"
|
description = "Modern Printer Profiling UI frontend for ArgyllCMS"
|
||||||
authors = ["Gordon"]
|
authors = ["Gordon"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|||||||
@@ -1,29 +1,32 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::process::Stdio;
|
use std::process::Stdio;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use tauri::AppHandle;
|
||||||
use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
|
use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
|
||||||
use tokio::process::{Child, Command};
|
use tokio::process::{Child, Command};
|
||||||
use tokio::sync::Mutex;
|
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 crate::events::{emit_error, emit_stderr, emit_stdout};
|
||||||
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
pub struct ProcessManager {
|
pub struct ProcessManager {
|
||||||
processes: Mutex<HashMap<String, Arc<Mutex<Child>>>>,
|
processes: Arc<Mutex<HashMap<String, Arc<Mutex<Child>>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProcessManager {
|
impl ProcessManager {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
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<String>, cwd: Option<String>) -> Result<(), String> {
|
pub async fn spawn(
|
||||||
|
&self,
|
||||||
|
app: AppHandle,
|
||||||
|
id: String,
|
||||||
|
binary: String,
|
||||||
|
args: Vec<String>,
|
||||||
|
cwd: Option<String>,
|
||||||
|
) -> Result<(), String> {
|
||||||
let mut command = Command::new(&binary);
|
let mut command = Command::new(&binary);
|
||||||
command.args(args);
|
command.args(args);
|
||||||
if let Some(dir) = cwd {
|
if let Some(dir) = cwd {
|
||||||
@@ -69,20 +72,30 @@ impl ProcessManager {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let child_arc = Arc::new(Mutex::new(child));
|
let child_arc = Arc::new(Mutex::new(child));
|
||||||
|
{
|
||||||
let mut processes = self.processes.lock().await;
|
let mut processes = self.processes.lock().await;
|
||||||
processes.insert(id.clone(), child_arc.clone());
|
processes.insert(id.clone(), child_arc.clone());
|
||||||
|
}
|
||||||
|
|
||||||
let id_clone_exit = id.clone();
|
let id_clone_exit = id.clone();
|
||||||
let app_clone_exit = app.clone();
|
let app_clone_exit = app.clone();
|
||||||
|
let processes_clone = self.processes.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
loop {
|
let exit_code = {
|
||||||
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
|
|
||||||
let mut c = child_arc.lock().await;
|
let mut c = child_arc.lock().await;
|
||||||
if let Ok(Some(status)) = c.try_wait() {
|
match c.wait().await {
|
||||||
crate::events::emit_exit(&app_clone_exit, &id_clone_exit, status.code().unwrap_or(1));
|
Ok(status) => status.code().unwrap_or(0),
|
||||||
break;
|
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(())
|
Ok(())
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "ICCery",
|
"productName": "ICCery",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"identifier": "com.gronod.iccery",
|
"identifier": "com.gronod.iccery",
|
||||||
"build": {
|
"build": {
|
||||||
"frontendDist": "../src"
|
"frontendDist": "../src"
|
||||||
|
|||||||
Reference in New Issue
Block a user