Просмотр исходного кода

Fix DNS cache lock goroutine leak

The cache deduplication in Client.Exchange uses a channel-based lock
per DNS question. Waiting goroutines blocked on <-cond without context
awareness, causing them to accumulate indefinitely when the owning
goroutine's transport call stalls. Add select on ctx.Done() so waiters
respect context cancellation and timeouts.
世界 1 неделя назад
Родитель
Сommit
aba8346bd6
1 измененных файлов с 10 добавлено и 2 удалено
  1. 10 2
      dns/client.go

+ 10 - 2
dns/client.go

@@ -144,7 +144,11 @@ func (c *Client) Exchange(ctx context.Context, transport adapter.DNSTransport, m
 		if c.cache != nil {
 			cond, loaded := c.cacheLock.LoadOrStore(question, make(chan struct{}))
 			if loaded {
-				<-cond
+				select {
+				case <-cond:
+				case <-ctx.Done():
+					return nil, ctx.Err()
+				}
 			} else {
 				defer func() {
 					c.cacheLock.Delete(question)
@@ -154,7 +158,11 @@ func (c *Client) Exchange(ctx context.Context, transport adapter.DNSTransport, m
 		} else if c.transportCache != nil {
 			cond, loaded := c.transportCacheLock.LoadOrStore(question, make(chan struct{}))
 			if loaded {
-				<-cond
+				select {
+				case <-cond:
+				case <-ctx.Done():
+					return nil, ctx.Err()
+				}
 			} else {
 				defer func() {
 					c.transportCacheLock.Delete(question)