From 3ac62152cbaa2f4e154c586a804d4e2c1a60c1fc Mon Sep 17 00:00:00 2001 From: Chenx Dust Date: Thu, 5 Feb 2026 15:57:01 +0800 Subject: [PATCH] fix: race condition of tcpConcurrent in dialer (#2556) --- component/dialer/dialer.go | 39 ++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/component/dialer/dialer.go b/component/dialer/dialer.go index 4bc69baa..2cd73f42 100644 --- a/component/dialer/dialer.go +++ b/component/dialer/dialer.go @@ -12,6 +12,7 @@ import ( "syscall" "time" + "github.com/metacubex/mihomo/common/atomic" "github.com/metacubex/mihomo/component/keepalive" "github.com/metacubex/mihomo/component/mptcp" "github.com/metacubex/mihomo/component/resolver" @@ -25,11 +26,8 @@ const ( type dialFunc func(ctx context.Context, network string, ips []netip.Addr, port string, opt option) (net.Conn, error) var ( - dialMux sync.Mutex - actualSingleStackDialContext = serialSingleStackDialContext - actualDualStackDialContext = serialDualStackDialContext - tcpConcurrent = false - fallbackTimeout = 300 * time.Millisecond + tcpConcurrent = atomic.NewBool(false) + fallbackTimeout = 300 * time.Millisecond ) func DialContext(ctx context.Context, network, address string, options ...Option) (net.Conn, error) { @@ -105,22 +103,11 @@ func ListenPacket(ctx context.Context, network, address string, rAddrPort netip. } func SetTcpConcurrent(concurrent bool) { - dialMux.Lock() - defer dialMux.Unlock() - tcpConcurrent = concurrent - if concurrent { - actualSingleStackDialContext = concurrentSingleStackDialContext - actualDualStackDialContext = concurrentDualStackDialContext - } else { - actualSingleStackDialContext = serialSingleStackDialContext - actualDualStackDialContext = serialDualStackDialContext - } + tcpConcurrent.Store(concurrent) } func GetTcpConcurrent() bool { - dialMux.Lock() - defer dialMux.Unlock() - return tcpConcurrent + return tcpConcurrent.Load() } func dialContext(ctx context.Context, network string, destination netip.Addr, port string, opt option) (net.Conn, error) { @@ -205,6 +192,22 @@ func ICMPControl(destination netip.Addr) func(network, address string, conn sysc } } +func actualSingleStackDialContext(ctx context.Context, network string, ips []netip.Addr, port string, opt option) (net.Conn, error) { + if tcpConcurrent.Load() { + return concurrentSingleStackDialContext(ctx, network, ips, port, opt) + } else { + return serialSingleStackDialContext(ctx, network, ips, port, opt) + } +} + +func actualDualStackDialContext(ctx context.Context, network string, ips []netip.Addr, port string, opt option) (net.Conn, error) { + if tcpConcurrent.Load() { + return concurrentDualStackDialContext(ctx, network, ips, port, opt) + } else { + return serialDualStackDialContext(ctx, network, ips, port, opt) + } +} + func serialSingleStackDialContext(ctx context.Context, network string, ips []netip.Addr, port string, opt option) (net.Conn, error) { return serialDialContext(ctx, network, ips, port, opt) }