From 862e2a5126b66ab5ea598fc45fd336d224128567 Mon Sep 17 00:00:00 2001 From: Tunglies <77394545+Tunglies@users.noreply.github.com> Date: Tue, 27 Oct 2026 19:13:19 +0800 Subject: [PATCH] refactor(app): extract common exit cleanup restart_app and quit duplicate the whole exit preparation: set the exiting flag, persist configs, run interactive cleanup, and on a failed core stop clear the flag, restore public DNS under the lifecycle lock on macOS, and send the stop-failed notice. Move that flow into run_exit_cleanup_flow next to clean_async, taking the notice variant as a parameter and returning the CleanupResult so each caller keeps its own tail: restart aborts before shutdown, quit always shuts down and exits with the cleanup code. --- src-tauri/src/feat/clash.rs | 33 ++------------------------------- src-tauri/src/feat/window.rs | 15 ++++++++++----- 2 files changed, 12 insertions(+), 36 deletions(-) diff --git a/src-tauri/src/feat/clash.rs b/src-tauri/src/feat/clash.rs index beddd2dec..9b1d84b3c 100644 --- a/src-tauri/src/feat/clash.rs +++ b/src-tauri/src/feat/clash.rs @@ -3,7 +3,7 @@ use crate::core::notify::{Refresh, announce}; use crate::{ config::{Config, MixedPort}, core::{CoreManager, handle, tray}, - feat::clean_async, + feat::run_exit_cleanup_flow, process::AsyncHandler, utils, }; @@ -31,38 +31,9 @@ pub async fn restart_clash_core() { pub async fn restart_app() { logging!(debug, Type::System, "启动重启应用流程"); - handle::Handle::global().set_is_exiting(); - - Config::apply_all_and_save_file().await; - - let cleanup_result = clean_async().await; - - logging!( - info, - Type::System, - "资源清理完成,退出代码: {}", - if cleanup_result.all_success { 0 } else { 1 } - ); + let cleanup_result = run_exit_cleanup_flow(NoticeStatus::AppRestartCoreStopFailed).await; if !cleanup_result.core_stopped { - handle::Handle::global().clear_is_exiting(); - // A failed stop may still have marked the core stopped, and exit cleanup skipped the DNS restore. - // A core that kept running keeps its DNS, whatever an unapplied config draft says. - #[cfg(target_os = "macos")] - { - let manager = CoreManager::global(); - let _lifecycle = manager.lifecycle_lock.lock().await; - if matches!( - *manager.get_running_mode(), - crate::core::manager::RunningMode::NotRunning - ) { - crate::utils::resolve::dns::sync_public_dns().await; - } - } - handle::Handle::notice( - NoticeStatus::AppRestartCoreStopFailed, - cleanup_result.stop_error.unwrap_or_default(), - ); return; } diff --git a/src-tauri/src/feat/window.rs b/src-tauri/src/feat/window.rs index f3bf5db7b..092d7267e 100644 --- a/src-tauri/src/feat/window.rs +++ b/src-tauri/src/feat/window.rs @@ -130,9 +130,7 @@ pub async fn open_or_close_dashboard() { logging!(info, Type::Window, "Window toggle result: {result:?}"); } -pub async fn quit() { - logging!(debug, Type::System, "启动退出流程"); - // 设置退出标志 +pub(crate) async fn run_exit_cleanup_flow(stop_failed_notice: NoticeStatus) -> CleanupResult { handle::Handle::global().set_is_exiting(); Config::apply_all_and_save_file().await; @@ -162,11 +160,18 @@ pub async fn quit() { } } handle::Handle::notice( - NoticeStatus::AppQuitCoreStopFailed, - cleanup_result.stop_error.unwrap_or_default(), + stop_failed_notice, + cleanup_result.stop_error.clone().unwrap_or_default(), ); } + cleanup_result +} + +pub async fn quit() { + logging!(debug, Type::System, "启动退出流程"); + let cleanup_result = run_exit_cleanup_flow(NoticeStatus::AppQuitCoreStopFailed).await; + utils::server::shutdown_embedded_server(); let app_handle = handle::Handle::app_handle(); app_handle.exit(if cleanup_result.all_success { 0 } else { 1 });