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" "syscall"
"time" "time"
"github.com/metacubex/mihomo/common/atomic"
"github.com/metacubex/mihomo/component/keepalive" "github.com/metacubex/mihomo/component/keepalive"
"github.com/metacubex/mihomo/component/mptcp" "github.com/metacubex/mihomo/component/mptcp"
"github.com/metacubex/mihomo/component/resolver" "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) type dialFunc func(ctx context.Context, network string, ips []netip.Addr, port string, opt option) (net.Conn, error)
var ( var (
dialMux sync.Mutex tcpConcurrent = atomic.NewBool(false)
actualSingleStackDialContext = serialSingleStackDialContext fallbackTimeout = 300 * time.Millisecond
actualDualStackDialContext = serialDualStackDialContext
tcpConcurrent = false
fallbackTimeout = 300 * time.Millisecond
) )
func DialContext(ctx context.Context, network, address string, options ...Option) (net.Conn, error) { 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) { func SetTcpConcurrent(concurrent bool) {
dialMux.Lock() tcpConcurrent.Store(concurrent)
defer dialMux.Unlock()
tcpConcurrent = concurrent
if concurrent {
actualSingleStackDialContext = concurrentSingleStackDialContext
actualDualStackDialContext = concurrentDualStackDialContext
} else {
actualSingleStackDialContext = serialSingleStackDialContext
actualDualStackDialContext = serialDualStackDialContext
}
} }
func GetTcpConcurrent() bool { func GetTcpConcurrent() bool {
dialMux.Lock() return tcpConcurrent.Load()
defer dialMux.Unlock()
return tcpConcurrent
} }
func dialContext(ctx context.Context, network string, destination netip.Addr, port string, opt option) (net.Conn, error) { 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) { func serialSingleStackDialContext(ctx context.Context, network string, ips []netip.Addr, port string, opt option) (net.Conn, error) {
return serialDialContext(ctx, network, ips, port, opt) return serialDialContext(ctx, network, ips, port, opt)
} }