fix(service): offer repair when a residual helper blocks Sidecar

A macOS helper left running without IPC made Sidecar refuse to start
while the service counted as not installed, so no repair was offered
(#8031, #8043). Treat such a helper as install evidence and record the
Sidecar refusal as unavailable so the repair dialog appears.
This commit is contained in:
wonfen
2026-09-24 20:24:40 +08:00
parent 78bf79cc09
commit 04d74ac48f
4 changed files with 21 additions and 3 deletions
+1
View File
@@ -14,6 +14,7 @@
**🍎 macOS**
- macOS 修复编辑规则时「规则内容」输入的首字母被自动转为大写的问题
- macOS 修复残留的服务进程导致内核无法启动、「继续使用 Sidecar」失败且无法修复的问题
</details>
+3 -1
View File
@@ -153,7 +153,9 @@ impl CoreManager {
#[tracing::instrument(skip_all, level = "info", fields(pid = tracing::field::Empty))]
pub(super) async fn start_core_by_sidecar(&self) -> Result<()> {
self.wait_for_sidecar_exit().await?;
let execution = clash_verge_service_ipc::execution::reserve_sidecar().await?;
let execution = clash_verge_service_ipc::execution::reserve_sidecar()
.await
.inspect_err(service::record_residual_service)?;
self.core_stopped();
let sidecar_ipc = dirs::sidecar_ipc_path()?;
+10 -2
View File
@@ -62,9 +62,17 @@ impl RunStateEnv for RealEnv {
}
async fn trusted_install_evidence(&self) -> Result<bool> {
tokio::task::spawn_blocking(crate::core::service::trusted_service_evidence)
let registered = tokio::task::spawn_blocking(crate::core::service::trusted_service_evidence)
.await
.context("service registration probe did not finish")?
.context("service registration probe did not finish")??;
// A helper that outlived its registration is a broken Service, not an absent one.
#[cfg(unix)]
if !registered && let Err(error) = clash_verge_service_ipc::execution::check_sidecar_available().await {
return Ok(error
.downcast_ref::<clash_verge_service_ipc::execution::ResidualServiceError>()
.is_some());
}
Ok(registered)
}
fn is_elevated(&self) -> bool {
+7
View File
@@ -805,6 +805,13 @@ fn record_service_start_refusal<E: RunStateEnv>(
refusal.into()
}
/// Sidecar stays blocked until a reinstall replaces the residual helper, so ask for repair.
pub(super) fn record_residual_service(error: &anyhow::Error) {
if let Some(residual) = error.downcast_ref::<clash_verge_service_ipc::execution::ResidualServiceError>() {
RUN_STATE.observe(ServiceHealth::Unavailable(residual.to_string()));
}
}
/// 尝试使用服务启动core
#[tracing::instrument(skip_all, level = "info", fields(generation = tracing::field::Empty, staging = tracing::field::Empty, code = tracing::field::Empty, outcome = tracing::field::Empty))]
pub(super) async fn start_with_existing_service(config_file: &Path) -> Result<()> {