From 81ce247eccc606e3c01d6c0fdd42eefcef44c39a Mon Sep 17 00:00:00 2001 From: wonfen Date: Mon, 21 Sep 2026 16:22:22 +0800 Subject: [PATCH] fix(service): repair initial owner identity and extend readiness wait --- Changelog.md | 2 ++ src-tauri/src/core/owner_identity.rs | 9 +++------ src-tauri/src/core/service.rs | 9 +++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Changelog.md b/Changelog.md index dc1a4f799..801e787ca 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,6 +5,8 @@ - 回退 2.5.4 引入的 DNS 覆写保护,修复重启后开关自动关闭 - 优化文件错误日志,显示具体文件路径和失败原因 +- 修复 DNS 覆写:空内容报错、初始值覆盖已有设置、已填写字段残留原配置、空字段在高级编辑器中缺失 +- 修复首次以管理员身份启动后,系统服务因数据目录所有权不符而拒绝启动内核的问题 diff --git a/src-tauri/src/core/owner_identity.rs b/src-tauri/src/core/owner_identity.rs index dd70401df..798abe9d6 100644 --- a/src-tauri/src/core/owner_identity.rs +++ b/src-tauri/src/core/owner_identity.rs @@ -392,13 +392,10 @@ mod windows_owner { } pub(super) fn repair_root_owner(root: &Path) -> Result<()> { + // Elevated Windows processes can create directories owned by Administrators. + std::fs::create_dir_all(root).context("failed to create the application data root before owner repair")?; // The Service canonicalizes before checking, so resolve junctions to the same object. - let root = match std::fs::canonicalize(root) { - Ok(path) => path, - // Nothing to repair: this process creates the root and owns it by construction. - Err(error) if error.kind() == std::io::ErrorKind::NotFound => return Ok(()), - Err(error) => return Err(error).context("failed to canonicalize the application data root"), - }; + let root = std::fs::canonicalize(root).context("failed to canonicalize the application data root")?; let root = root.as_path(); let sid = current_sid()?; diff --git a/src-tauri/src/core/service.rs b/src-tauri/src/core/service.rs index ec7195a75..499353f51 100644 --- a/src-tauri/src/core/service.rs +++ b/src-tauri/src/core/service.rs @@ -1963,12 +1963,13 @@ async fn recover_after_owner_loss_while_locked(reason: OwnerRecoveryReason) { #[tracing::instrument(skip_all, level = "info", fields(attempts = tracing::field::Empty, interval_ms = tracing::field::Empty, outcome = tracing::field::Empty))] async fn wait_for_service_ipc() -> Result<()> { const CONTEXT: &str = "service IPC did not become available"; - let config = ServiceManager::config(); + const READY_ATTEMPTS: usize = 61; + const READY_INTERVAL: Duration = Duration::from_millis(500); let span = tracing::Span::current(); - span.record("attempts", config.max_retries); - span.record("interval_ms", config.retry_delay.as_millis() as u64); + span.record("attempts", READY_ATTEMPTS); + span.record("interval_ms", READY_INTERVAL.as_millis() as u64); - match RUN_STATE.await_ready(config.max_retries, config.retry_delay).await { + match RUN_STATE.await_ready(READY_ATTEMPTS, READY_INTERVAL).await { Ok(_) => { tracing::Span::current().record("outcome", "ready"); Ok(())