fix(sysproxy): stop turning a missing network service into a hard failure

This commit is contained in:
wonfen
2026-09-02 11:46:37 +08:00
parent 78cc4dc532
commit ef042ddf82
7 changed files with 238 additions and 188 deletions
+17 -13
View File
@@ -4,7 +4,7 @@ use crate::core::handle::Handle;
use crate::core::manager::CLASH_LOGGER;
use crate::core::proxy_control::{self, SysproxyFailure};
use crate::core::service::{SERVICE_MANAGER, ServiceStatus};
use anyhow::{Result, ensure};
use anyhow::Result;
use clash_verge_logging::{Type, logging};
use scopeguard::defer;
use smartstring::alias::String;
@@ -129,20 +129,24 @@ where
{
match (running_mode, proxy_intent) {
(RunningMode::NotRunning, _) => {}
// Do not hand the OS to another owner while the old guard may still write.
(RunningMode::Sidecar, ProxyStopIntent::HandOverToService) => ensure!(
stop_guard().await,
"the system proxy guard did not stop in time; not handing the proxy to the service"
),
(RunningMode::Service, _) if is_macos => ensure!(
stop_guard().await,
"the system proxy guard did not stop in time; not stopping the service-owned core"
),
// A guard that will not stop must not block the core from stopping.
(RunningMode::Sidecar, ProxyStopIntent::HandOverToService) => warn_if_guard_lingers(stop_guard().await),
(RunningMode::Service, _) if is_macos => warn_if_guard_lingers(stop_guard().await),
(RunningMode::Service | RunningMode::Sidecar, _) => clear_proxy().await?,
}
stop_core().await
}
fn warn_if_guard_lingers(stopped: bool) {
if !stopped {
logging!(
warn,
Type::Core,
"the system proxy guard did not stop in time; stopping the core anyway"
);
}
}
async fn run_core_start_transition<Start, StartFuture, Ready, Apply, ApplyFuture>(
start_core: Start,
core_is_ready: Ready,
@@ -951,7 +955,7 @@ mod tests {
}
#[tokio::test]
async fn a_guard_that_would_not_stop_keeps_the_core_where_it_is() {
async fn a_guard_that_would_not_stop_does_not_block_the_core_from_stopping() {
for (mode, intent) in [
(RunningMode::Sidecar, ProxyStopIntent::HandOverToService),
(RunningMode::Service, ProxyStopIntent::Clear),
@@ -968,8 +972,8 @@ mod tests {
)
.await;
assert!(result.is_err(), "{mode:?} {intent:?}");
assert!(calls.lock().is_empty(), "{mode:?} {intent:?}: {:?}", *calls.lock());
assert!(result.is_ok(), "{mode:?} {intent:?}");
assert_eq!(&*calls.lock(), &["core_stop"], "{mode:?} {intent:?}");
}
}