fix: race condition of tcpConcurrent in dialer (#2556)

This commit is contained in:
Chenx Dust
2026-02-05 15:57:01 +08:00
committed by GitHub
parent 5516ca18fd
commit 3ac62152cb

View File

@@ -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)
}