mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-11-09 11:52:08 +08:00
fix(tun): fall back to sidecar when service is absent
This commit is contained in:
+29
-12
@@ -1,4 +1,4 @@
|
||||
//! Disables TUN when the current Run State cannot support it.
|
||||
//! Reconciles TUN with current Core and Service availability.
|
||||
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
@@ -10,40 +10,57 @@ use crate::{
|
||||
core::{handle::Handle, manager::RunningMode, runstate::RUN_STATE},
|
||||
};
|
||||
|
||||
/// Set while an automatic TUN disable is being written.
|
||||
///
|
||||
/// Drops new requests during the write to prevent recursive retries. No-op reconciliations leave
|
||||
/// it clear so later state changes can still be processed.
|
||||
/// Prevents recursive runtime disable writes.
|
||||
static DISABLING_TUN: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
/// Suppress TUN for this Windows session when startup confirms the Service is absent.
|
||||
/// The saved preference remains available for a later Service install.
|
||||
pub async fn reconcile_startup_tun_availability() {
|
||||
if !cfg!(target_os = "windows") {
|
||||
return;
|
||||
}
|
||||
|
||||
// Read fresh state after prior config writes complete.
|
||||
let _config_write = Config::lock_config_write().await;
|
||||
let tun_enabled = Config::verge().await.data_arc().enable_tun_mode.unwrap_or(false);
|
||||
if !RUN_STATE.state().startup_tun_should_be_disabled(tun_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
logging!(
|
||||
info,
|
||||
Type::Setup,
|
||||
"Windows Service is not installed; suppressing TUN mode so the Core can start on Sidecar"
|
||||
);
|
||||
Config::suppress_tun_for_session().await;
|
||||
}
|
||||
|
||||
/// Disable TUN when the current settled Run State cannot support it.
|
||||
pub async fn reconcile_tun_availability() {
|
||||
// Coalesce all reconciliation requests while a disable write is in flight.
|
||||
if DISABLING_TUN.load(Ordering::Acquire) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Wait for any config transaction, then decide from fresh state and committed config.
|
||||
// Re-read state and committed config after prior writes complete.
|
||||
let config_write = Config::lock_config_write().await;
|
||||
let state = RUN_STATE.state();
|
||||
|
||||
// Startup may still install the Service and uses this setting to decide whether to prompt.
|
||||
// Startup uses the narrower session-suppression path above.
|
||||
if matches!(state.mode, RunningMode::NotRunning) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Sidecar fallback suppresses TUN for this session without changing the saved preference.
|
||||
if Config::tun_suppressed_for_session() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Do not rewrite the saved preference based on an uncommitted draft from a legacy writer.
|
||||
// Legacy writers may still hold an uncommitted draft.
|
||||
let tun_enabled = Config::verge().await.data_arc().enable_tun_mode.unwrap_or(false);
|
||||
if !state.tun_should_be_disabled(tun_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The config lock already serializes writers; the flag only sheds newly spawned work.
|
||||
// The flag coalesces newly spawned tasks while the config lock serializes writers.
|
||||
DISABLING_TUN.store(true, Ordering::Release);
|
||||
defer! {
|
||||
DISABLING_TUN.store(false, Ordering::Release);
|
||||
@@ -59,7 +76,7 @@ pub async fn reconcile_tun_availability() {
|
||||
..IVerge::default()
|
||||
};
|
||||
|
||||
// Avoid recursively reconciling this internal patch.
|
||||
// Skip recursive reconciliation for this internal patch.
|
||||
match super::apply_verge_patch_locked(&config_write, &patch, false).await {
|
||||
Ok(()) => Handle::notice_message("tun_mode::auto_disabled", ""),
|
||||
Err(error) => {
|
||||
|
||||
Reference in New Issue
Block a user