diff --git a/src-tauri/src/core/core.rs b/src-tauri/src/core/core.rs index f50b9c53..863f744f 100644 --- a/src-tauri/src/core/core.rs +++ b/src-tauri/src/core/core.rs @@ -5,27 +5,24 @@ use crate::utils::dirs; use anyhow::{bail, Result}; use once_cell::sync::OnceCell; use serde_yaml::Mapping; -use std::ffi::OsStr; use std::{sync::Arc, time::Duration}; -use sysinfo::ProcessesToUpdate; -use sysinfo::{ProcessRefreshKind, RefreshKind, System}; -use tauri_plugin_shell::process::CommandEvent; +use tauri_plugin_shell::process::{CommandChild, CommandEvent}; use tauri_plugin_shell::ShellExt; use tokio::sync::Mutex; - use tokio::time::sleep; #[derive(Debug)] pub struct CoreManager { running: Arc>, + sidecar: Arc>>, } impl CoreManager { pub fn global() -> &'static CoreManager { static CORE_MANAGER: OnceCell = OnceCell::new(); - CORE_MANAGER.get_or_init(|| CoreManager { running: Arc::new(Mutex::new(false)), + sidecar: Arc::new(Mutex::new(None)), }) } @@ -79,8 +76,6 @@ impl CoreManager { return Ok(()); } - let clash_core = { Config::verge().latest().clash_core.clone() }; - let clash_core = clash_core.unwrap_or("verge-mihomo".into()); // 关闭tun模式 let mut disable = Mapping::new(); let mut tun = Mapping::new(); @@ -89,11 +84,15 @@ impl CoreManager { log::debug!(target: "app", "disable tun mode"); log_err!(clash_api::patch_configs(&disable).await); - // 服务模式 - log::debug!(target: "app", "stop the core by service"); - log_err!(service::stop_core_by_service().await); - - kill_processes_by_name(clash_core.as_str()); + if let Some(sidecar) = self.sidecar.lock().await.take() { + let _ = sidecar.kill(); + } else { + // 服务模式 + if service::check_service().await.is_ok() { + log::debug!(target: "app", "stop the core by service"); + log_err!(service::stop_core_by_service().await); + } + } *running = false; Ok(()) @@ -113,25 +112,17 @@ impl CoreManager { // 服务模式 let service_enable = { Config::verge().latest().enable_service_mode }; let service_enable = service_enable.unwrap_or(false); - if service_enable { - // 服务模式启动失败就直接运行sidecar - log::debug!(target: "app", "try to run core in service mode"); - let res = async { - service::check_service().await?; - service::run_core_by_service(&config_path).await - } - .await; - match res { - Ok(_) => { - return { - *running = true; - Ok(()) - } - } - Err(err) => { - log::error!(target: "app start service err", "{err}"); + if service::check_service().await.is_ok() { + log::debug!(target: "app", "try to run core in service mode"); + if service_enable { + service::run_core_by_service(&config_path).await?; + let mut sidecar = self.sidecar.lock().await; + if sidecar.is_some() { + sidecar.take(); } + *running = true; + return Ok(()); } } @@ -141,7 +132,10 @@ impl CoreManager { let args = vec!["-d", app_dir, "-f", config_path]; let app_handle = handle::Handle::global().app_handle().unwrap(); let cmd = app_handle.shell().sidecar(clash_core)?; - let (mut rx, _) = cmd.args(args).spawn()?; + let (mut rx, cmd_child) = cmd.args(args).spawn()?; + let mut sidecar = self.sidecar.lock().await; + + *sidecar = Some(cmd_child); tauri::async_runtime::spawn(async move { while let Some(event) = rx.recv().await { @@ -247,17 +241,3 @@ impl CoreManager { Ok(()) } } - -fn kill_processes_by_name(process_name: &str) { - let mut system = System::new_with_specifics( - RefreshKind::new().with_processes(ProcessRefreshKind::everything()), - ); - - system.refresh_processes(ProcessesToUpdate::All); - let process_name = OsStr::new(process_name); - let procs = system.processes_by_name(process_name); - for proc in procs { - log::debug!(target: "app", "Killing process: {:?}", proc.name()); - proc.kill(); - } -} diff --git a/src-tauri/src/core/service.rs b/src-tauri/src/core/service.rs index 9e67ce77..e27c3684 100644 --- a/src-tauri/src/core/service.rs +++ b/src-tauri/src/core/service.rs @@ -4,9 +4,8 @@ use anyhow::{bail, Context, Result}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::path::PathBuf; -use std::time::Duration; use std::{env::current_exe, process::Command as StdCommand}; -use tokio::time::sleep; +use tokio::time::Duration; // Windows only @@ -268,6 +267,7 @@ pub async fn check_service() -> Result { let url = format!("{SERVICE_URL}/get_clash"); let response = reqwest::ClientBuilder::new() .no_proxy() + .timeout(Duration::from_secs(3)) .build()? .get(url) .send() @@ -282,13 +282,6 @@ pub async fn check_service() -> Result { /// start the clash by service pub(super) async fn run_core_by_service(config_file: &PathBuf) -> Result<()> { - let status = check_service().await?; - - if status.code == 0 { - stop_core_by_service().await?; - sleep(Duration::from_secs(1)).await; - } - let clash_core = { Config::verge().latest().clash_core.clone() }; let clash_core = clash_core.unwrap_or("verge-mihomo".into()); @@ -313,40 +306,28 @@ pub(super) async fn run_core_by_service(config_file: &PathBuf) -> Result<()> { map.insert("log_file", log_path); let url = format!("{SERVICE_URL}/start_clash"); - let res = reqwest::ClientBuilder::new() + let _ = reqwest::ClientBuilder::new() .no_proxy() .build()? .post(url) .json(&map) .send() - .await? - .json::() .await .context("failed to connect to the Clash Verge Service")?; - if res.code != 0 { - bail!(res.msg); - } - Ok(()) } /// stop the clash by service pub(super) async fn stop_core_by_service() -> Result<()> { let url = format!("{SERVICE_URL}/stop_clash"); - let res = reqwest::ClientBuilder::new() + let _ = reqwest::ClientBuilder::new() .no_proxy() .build()? .post(url) .send() - .await? - .json::() .await .context("failed to connect to the Clash Verge Service")?; - if res.code != 0 { - bail!(res.msg); - } - Ok(()) }