Fix DNS query loopback deadlock from shared dedup lock

This commit is contained in:
世界
2026-06-20 20:36:19 +08:00
parent 4e1af0600b
commit 72a8723e13

View File

@@ -41,9 +41,9 @@ type Client struct {
initRDRCFunc func() adapter.RDRCStore initRDRCFunc func() adapter.RDRCStore
logger logger.ContextLogger logger logger.ContextLogger
cache freelru.Cache[dns.Question, *dns.Msg] cache freelru.Cache[dns.Question, *dns.Msg]
cacheLock compatible.Map[dns.Question, chan struct{}] cacheLock compatible.Map[transportCacheKey, chan struct{}]
transportCache freelru.Cache[transportCacheKey, *dns.Msg] transportCache freelru.Cache[transportCacheKey, *dns.Msg]
transportCacheLock compatible.Map[dns.Question, chan struct{}] transportCacheLock compatible.Map[transportCacheKey, chan struct{}]
} }
type ClientOptions struct { type ClientOptions struct {
@@ -138,8 +138,9 @@ func (c *Client) Exchange(ctx context.Context, transport adapter.DNSTransport, m
!options.ClientSubnet.IsValid() !options.ClientSubnet.IsValid()
disableCache := !isSimpleRequest || c.disableCache || options.DisableCache disableCache := !isSimpleRequest || c.disableCache || options.DisableCache
if !disableCache { if !disableCache {
cacheKey := transportCacheKey{Question: question, transportTag: transport.Tag()}
if c.cache != nil { if c.cache != nil {
cond, loaded := c.cacheLock.LoadOrStore(question, make(chan struct{})) cond, loaded := c.cacheLock.LoadOrStore(cacheKey, make(chan struct{}))
if loaded { if loaded {
select { select {
case <-cond: case <-cond:
@@ -148,12 +149,12 @@ func (c *Client) Exchange(ctx context.Context, transport adapter.DNSTransport, m
} }
} else { } else {
defer func() { defer func() {
c.cacheLock.Delete(question) c.cacheLock.Delete(cacheKey)
close(cond) close(cond)
}() }()
} }
} else if c.transportCache != nil { } else if c.transportCache != nil {
cond, loaded := c.transportCacheLock.LoadOrStore(question, make(chan struct{})) cond, loaded := c.transportCacheLock.LoadOrStore(cacheKey, make(chan struct{}))
if loaded { if loaded {
select { select {
case <-cond: case <-cond:
@@ -162,7 +163,7 @@ func (c *Client) Exchange(ctx context.Context, transport adapter.DNSTransport, m
} }
} else { } else {
defer func() { defer func() {
c.transportCacheLock.Delete(question) c.transportCacheLock.Delete(cacheKey)
close(cond) close(cond)
}() }()
} }