mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-01-29 00:35:38 +08:00
fix: manage setup Mutex crash (#3995)
* Revert "Revert "refactor: Replace std::sync::Mutex with parking_lot::Mutex for improved performance and consistency in multiple files" (#3990)"
This reverts commit 667844aa12.
* refactor: Manage lightweight state in the app setup and clean up unused proxy client code
* refactor: Move macOS-specific Manager import under conditional compilation
This commit is contained in:
@@ -8,7 +8,8 @@ pub fn use_script(
|
|||||||
name: String,
|
name: String,
|
||||||
) -> Result<(Mapping, Vec<(String, String)>)> {
|
) -> Result<(Mapping, Vec<(String, String)>)> {
|
||||||
use boa_engine::{native_function::NativeFunction, Context, JsValue, Source};
|
use boa_engine::{native_function::NativeFunction, Context, JsValue, Source};
|
||||||
use std::sync::{Arc, Mutex};
|
use parking_lot::Mutex;
|
||||||
|
use std::sync::Arc;
|
||||||
let mut context = Context::default();
|
let mut context = Context::default();
|
||||||
|
|
||||||
let outputs = Arc::new(Mutex::new(vec![]));
|
let outputs = Arc::new(Mutex::new(vec![]));
|
||||||
@@ -24,7 +25,7 @@ pub fn use_script(
|
|||||||
let level = level.to_std_string().unwrap();
|
let level = level.to_std_string().unwrap();
|
||||||
let data = args.get(1).unwrap().to_string(context)?;
|
let data = args.get(1).unwrap().to_string(context)?;
|
||||||
let data = data.to_std_string().unwrap();
|
let data = data.to_std_string().unwrap();
|
||||||
let mut out = copy_outputs.lock().unwrap();
|
let mut out = copy_outputs.lock();
|
||||||
out.push((level, data));
|
out.push((level, data));
|
||||||
Ok(JsValue::undefined())
|
Ok(JsValue::undefined())
|
||||||
},
|
},
|
||||||
@@ -67,7 +68,7 @@ pub fn use_script(
|
|||||||
// 直接解析JSON结果,不做其他解析
|
// 直接解析JSON结果,不做其他解析
|
||||||
let res: Result<Mapping, Error> = parse_json_safely(&result);
|
let res: Result<Mapping, Error> = parse_json_safely(&result);
|
||||||
|
|
||||||
let mut out = outputs.lock().unwrap();
|
let mut out = outputs.lock();
|
||||||
match res {
|
match res {
|
||||||
Ok(config) => Ok((use_lowercase(config), out.to_vec())),
|
Ok(config) => Ok((use_lowercase(config), out.to_vec())),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
|||||||
@@ -13,8 +13,10 @@ use crate::{
|
|||||||
utils::{resolve, resolve::resolve_scheme, server},
|
utils::{resolve, resolve::resolve_scheme, server},
|
||||||
};
|
};
|
||||||
use config::Config;
|
use config::Config;
|
||||||
use std::sync::{Mutex, Once};
|
use parking_lot::Mutex;
|
||||||
|
use std::sync::Once;
|
||||||
use tauri::AppHandle;
|
use tauri::AppHandle;
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
use tauri::Manager;
|
use tauri::Manager;
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
use tauri_plugin_autostart::MacosLauncher;
|
use tauri_plugin_autostart::MacosLauncher;
|
||||||
@@ -41,14 +43,14 @@ impl AppHandleManager {
|
|||||||
/// Initialize the app handle manager with an app handle.
|
/// Initialize the app handle manager with an app handle.
|
||||||
pub fn init(&self, handle: AppHandle) {
|
pub fn init(&self, handle: AppHandle) {
|
||||||
self.init.call_once(|| {
|
self.init.call_once(|| {
|
||||||
let mut app_handle = self.inner.lock().unwrap();
|
let mut app_handle = self.inner.lock();
|
||||||
*app_handle = Some(handle);
|
*app_handle = Some(handle);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the app handle if it has been initialized.
|
/// Get the app handle if it has been initialized.
|
||||||
pub fn get(&self) -> Option<AppHandle> {
|
pub fn get(&self) -> Option<AppHandle> {
|
||||||
self.inner.lock().unwrap().clone()
|
self.inner.lock().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the app handle, panics if it hasn't been initialized.
|
/// Get the app handle, panics if it hasn't been initialized.
|
||||||
@@ -59,7 +61,7 @@ impl AppHandleManager {
|
|||||||
pub fn set_activation_policy_regular(&self) {
|
pub fn set_activation_policy_regular(&self) {
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
{
|
{
|
||||||
let app_handle = self.inner.lock().unwrap();
|
let app_handle = self.inner.lock();
|
||||||
let app_handle = app_handle.as_ref().unwrap();
|
let app_handle = app_handle.as_ref().unwrap();
|
||||||
let _ = app_handle.set_activation_policy(tauri::ActivationPolicy::Regular);
|
let _ = app_handle.set_activation_policy(tauri::ActivationPolicy::Regular);
|
||||||
}
|
}
|
||||||
@@ -68,7 +70,7 @@ impl AppHandleManager {
|
|||||||
pub fn set_activation_policy_accessory(&self) {
|
pub fn set_activation_policy_accessory(&self) {
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
{
|
{
|
||||||
let app_handle = self.inner.lock().unwrap();
|
let app_handle = self.inner.lock();
|
||||||
let app_handle = app_handle.as_ref().unwrap();
|
let app_handle = app_handle.as_ref().unwrap();
|
||||||
let _ = app_handle.set_activation_policy(tauri::ActivationPolicy::Accessory);
|
let _ = app_handle.set_activation_policy(tauri::ActivationPolicy::Accessory);
|
||||||
}
|
}
|
||||||
@@ -77,7 +79,7 @@ impl AppHandleManager {
|
|||||||
pub fn set_activation_policy_prohibited(&self) {
|
pub fn set_activation_policy_prohibited(&self) {
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
{
|
{
|
||||||
let app_handle = self.inner.lock().unwrap();
|
let app_handle = self.inner.lock();
|
||||||
let app_handle = app_handle.as_ref().unwrap();
|
let app_handle = app_handle.as_ref().unwrap();
|
||||||
let _ = app_handle.set_activation_policy(tauri::ActivationPolicy::Prohibited);
|
let _ = app_handle.set_activation_policy(tauri::ActivationPolicy::Prohibited);
|
||||||
}
|
}
|
||||||
@@ -134,6 +136,7 @@ pub fn run() {
|
|||||||
.plugin(tauri_plugin_dialog::init())
|
.plugin(tauri_plugin_dialog::init())
|
||||||
.plugin(tauri_plugin_shell::init())
|
.plugin(tauri_plugin_shell::init())
|
||||||
.plugin(tauri_plugin_deep_link::init())
|
.plugin(tauri_plugin_deep_link::init())
|
||||||
|
.manage(Mutex::new(state::lightweight::LightWeightState::default()))
|
||||||
.setup(|app| {
|
.setup(|app| {
|
||||||
logging!(info, Type::Setup, true, "开始应用初始化...");
|
logging!(info, Type::Setup, true, "开始应用初始化...");
|
||||||
let mut auto_start_plugin_builder = tauri_plugin_autostart::Builder::new();
|
let mut auto_start_plugin_builder = tauri_plugin_autostart::Builder::new();
|
||||||
@@ -213,8 +216,6 @@ pub fn run() {
|
|||||||
logging!(error, Type::Setup, true, "初始化资源失败: {}", e);
|
logging!(error, Type::Setup, true, "初始化资源失败: {}", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
app.manage(Mutex::new(state::lightweight::LightWeightState::default()));
|
|
||||||
|
|
||||||
logging!(info, Type::Setup, true, "初始化完成,继续执行");
|
logging!(info, Type::Setup, true, "初始化完成,继续执行");
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -13,10 +13,8 @@ use crate::AppHandleManager;
|
|||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use delay_timer::prelude::TaskBuilder;
|
use delay_timer::prelude::TaskBuilder;
|
||||||
use std::sync::{
|
use parking_lot::Mutex;
|
||||||
atomic::{AtomicBool, Ordering},
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
Mutex,
|
|
||||||
};
|
|
||||||
use tauri::{Listener, Manager};
|
use tauri::{Listener, Manager};
|
||||||
|
|
||||||
const LIGHT_WEIGHT_TASK_UID: &str = "light_weight_task";
|
const LIGHT_WEIGHT_TASK_UID: &str = "light_weight_task";
|
||||||
@@ -30,7 +28,7 @@ where
|
|||||||
{
|
{
|
||||||
let app_handle = handle::Handle::global().app_handle().unwrap();
|
let app_handle = handle::Handle::global().app_handle().unwrap();
|
||||||
let state = app_handle.state::<Mutex<LightWeightState>>();
|
let state = app_handle.state::<Mutex<LightWeightState>>();
|
||||||
let mut guard = state.lock().unwrap();
|
let mut guard = state.lock();
|
||||||
f(&mut guard)
|
f(&mut guard)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
use parking_lot::Mutex;
|
||||||
use reqwest::{Client, ClientBuilder, Proxy, RequestBuilder, Response};
|
use reqwest::{Client, ClientBuilder, Proxy, RequestBuilder, Response};
|
||||||
use std::{
|
use std::{
|
||||||
sync::{Arc, Mutex, Once},
|
sync::{Arc, Once},
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
use tokio::runtime::{Builder, Runtime};
|
use tokio::runtime::{Builder, Runtime};
|
||||||
@@ -78,7 +79,7 @@ impl NetworkManager {
|
|||||||
.build()
|
.build()
|
||||||
.expect("Failed to build no_proxy client");
|
.expect("Failed to build no_proxy client");
|
||||||
|
|
||||||
let mut no_proxy_guard = NETWORK_MANAGER.no_proxy_client.lock().unwrap();
|
let mut no_proxy_guard = NETWORK_MANAGER.no_proxy_client.lock();
|
||||||
*no_proxy_guard = Some(no_proxy_client);
|
*no_proxy_guard = Some(no_proxy_client);
|
||||||
|
|
||||||
logging!(info, Type::Network, true, "网络管理器初始化完成");
|
logging!(info, Type::Network, true, "网络管理器初始化完成");
|
||||||
@@ -87,16 +88,16 @@ impl NetworkManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn record_connection_error(&self, error: &str) {
|
fn record_connection_error(&self, error: &str) {
|
||||||
let mut last_error = self.last_connection_error.lock().unwrap();
|
let mut last_error = self.last_connection_error.lock();
|
||||||
*last_error = Some((Instant::now(), error.to_string()));
|
*last_error = Some((Instant::now(), error.to_string()));
|
||||||
|
|
||||||
let mut error_count = self.connection_error_count.lock().unwrap();
|
let mut error_count = self.connection_error_count.lock();
|
||||||
*error_count += 1;
|
*error_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_reset_clients(&self) -> bool {
|
fn should_reset_clients(&self) -> bool {
|
||||||
let error_count = *self.connection_error_count.lock().unwrap();
|
let error_count = *self.connection_error_count.lock();
|
||||||
let last_error = self.last_connection_error.lock().unwrap();
|
let last_error = self.last_connection_error.lock();
|
||||||
|
|
||||||
if error_count > 5 {
|
if error_count > 5 {
|
||||||
return true;
|
return true;
|
||||||
@@ -114,132 +115,23 @@ impl NetworkManager {
|
|||||||
pub fn reset_clients(&self) {
|
pub fn reset_clients(&self) {
|
||||||
logging!(info, Type::Network, true, "正在重置所有HTTP客户端");
|
logging!(info, Type::Network, true, "正在重置所有HTTP客户端");
|
||||||
{
|
{
|
||||||
let mut client = self.self_proxy_client.lock().unwrap();
|
let mut client = self.self_proxy_client.lock();
|
||||||
*client = None;
|
*client = None;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let mut client = self.system_proxy_client.lock().unwrap();
|
let mut client = self.system_proxy_client.lock();
|
||||||
*client = None;
|
*client = None;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let mut client = self.no_proxy_client.lock().unwrap();
|
let mut client = self.no_proxy_client.lock();
|
||||||
*client = None;
|
*client = None;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let mut error_count = self.connection_error_count.lock().unwrap();
|
let mut error_count = self.connection_error_count.lock();
|
||||||
*error_count = 0;
|
*error_count = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
/// 获取或创建自代理客户端
|
|
||||||
fn get_or_create_self_proxy_client(&self) -> Client {
|
|
||||||
if self.should_reset_clients() {
|
|
||||||
self.reset_clients();
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut client_guard = self.self_proxy_client.lock().unwrap();
|
|
||||||
|
|
||||||
if client_guard.is_none() {
|
|
||||||
let port = Config::verge()
|
|
||||||
.latest_ref()
|
|
||||||
.verge_mixed_port
|
|
||||||
.unwrap_or(Config::clash().latest_ref().get_mixed_port());
|
|
||||||
|
|
||||||
let proxy_scheme = format!("http://127.0.0.1:{port}");
|
|
||||||
|
|
||||||
let mut builder = ClientBuilder::new()
|
|
||||||
.use_rustls_tls()
|
|
||||||
.pool_max_idle_per_host(POOL_MAX_IDLE_PER_HOST)
|
|
||||||
.pool_idle_timeout(POOL_IDLE_TIMEOUT)
|
|
||||||
.connect_timeout(DEFAULT_CONNECT_TIMEOUT)
|
|
||||||
.timeout(DEFAULT_REQUEST_TIMEOUT)
|
|
||||||
.http2_initial_stream_window_size(H2_STREAM_WINDOW_SIZE)
|
|
||||||
.http2_initial_connection_window_size(H2_CONNECTION_WINDOW_SIZE)
|
|
||||||
.http2_adaptive_window(true)
|
|
||||||
.http2_keep_alive_interval(Some(H2_KEEP_ALIVE_INTERVAL))
|
|
||||||
.http2_keep_alive_timeout(H2_KEEP_ALIVE_TIMEOUT)
|
|
||||||
.http2_max_frame_size(H2_MAX_FRAME_SIZE)
|
|
||||||
.tcp_keepalive(Some(Duration::from_secs(10)))
|
|
||||||
.http2_max_header_list_size(16 * 1024);
|
|
||||||
|
|
||||||
if let Ok(proxy) = Proxy::http(&proxy_scheme) {
|
|
||||||
builder = builder.proxy(proxy);
|
|
||||||
}
|
|
||||||
if let Ok(proxy) = Proxy::https(&proxy_scheme) {
|
|
||||||
builder = builder.proxy(proxy);
|
|
||||||
}
|
|
||||||
if let Ok(proxy) = Proxy::all(&proxy_scheme) {
|
|
||||||
builder = builder.proxy(proxy);
|
|
||||||
}
|
|
||||||
|
|
||||||
let client = builder.build().expect("Failed to build self_proxy client");
|
|
||||||
*client_guard = Some(client);
|
|
||||||
}
|
|
||||||
|
|
||||||
client_guard.as_ref().unwrap().clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 获取或创建系统代理客户端
|
|
||||||
fn get_or_create_system_proxy_client(&self) -> Client {
|
|
||||||
if self.should_reset_clients() {
|
|
||||||
self.reset_clients();
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut client_guard = self.system_proxy_client.lock().unwrap();
|
|
||||||
|
|
||||||
if client_guard.is_none() {
|
|
||||||
use sysproxy::Sysproxy;
|
|
||||||
|
|
||||||
let mut builder = ClientBuilder::new()
|
|
||||||
.use_rustls_tls()
|
|
||||||
.pool_max_idle_per_host(POOL_MAX_IDLE_PER_HOST)
|
|
||||||
.pool_idle_timeout(POOL_IDLE_TIMEOUT)
|
|
||||||
.connect_timeout(DEFAULT_CONNECT_TIMEOUT)
|
|
||||||
.timeout(DEFAULT_REQUEST_TIMEOUT)
|
|
||||||
.http2_initial_stream_window_size(H2_STREAM_WINDOW_SIZE)
|
|
||||||
.http2_initial_connection_window_size(H2_CONNECTION_WINDOW_SIZE)
|
|
||||||
.http2_adaptive_window(true)
|
|
||||||
.http2_keep_alive_interval(Some(H2_KEEP_ALIVE_INTERVAL))
|
|
||||||
.http2_keep_alive_timeout(H2_KEEP_ALIVE_TIMEOUT)
|
|
||||||
.http2_max_frame_size(H2_MAX_FRAME_SIZE)
|
|
||||||
.tcp_keepalive(Some(Duration::from_secs(10)))
|
|
||||||
.http2_max_header_list_size(16 * 1024);
|
|
||||||
|
|
||||||
if let Ok(p @ Sysproxy { enable: true, .. }) = Sysproxy::get_system_proxy() {
|
|
||||||
let proxy_scheme = format!("http://{}:{}", p.host, p.port);
|
|
||||||
|
|
||||||
if let Ok(proxy) = Proxy::http(&proxy_scheme) {
|
|
||||||
builder = builder.proxy(proxy);
|
|
||||||
}
|
|
||||||
if let Ok(proxy) = Proxy::https(&proxy_scheme) {
|
|
||||||
builder = builder.proxy(proxy);
|
|
||||||
}
|
|
||||||
if let Ok(proxy) = Proxy::all(&proxy_scheme) {
|
|
||||||
builder = builder.proxy(proxy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let client = builder
|
|
||||||
.build()
|
|
||||||
.expect("Failed to build system_proxy client");
|
|
||||||
*client_guard = Some(client);
|
|
||||||
}
|
|
||||||
|
|
||||||
client_guard.as_ref().unwrap().clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 根据代理设置选择合适的客户端
|
|
||||||
pub fn get_client(&self, proxy_type: ProxyType) -> Client {
|
|
||||||
match proxy_type {
|
|
||||||
ProxyType::NoProxy => {
|
|
||||||
let client_guard = self.no_proxy_client.lock().unwrap();
|
|
||||||
client_guard.as_ref().unwrap().clone()
|
|
||||||
}
|
|
||||||
ProxyType::SelfProxy => self.get_or_create_self_proxy_client(),
|
|
||||||
ProxyType::SystemProxy => self.get_or_create_system_proxy_client(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/// 创建带有自定义选项的HTTP请求
|
/// 创建带有自定义选项的HTTP请求
|
||||||
pub fn create_request(
|
pub fn create_request(
|
||||||
&self,
|
&self,
|
||||||
|
|||||||
Reference in New Issue
Block a user