Merge pull request #1882 from safing/fix/s25-fix-deadlock-and-connectivity-loss

fix: Deadlock in TCP resolver
This commit is contained in:
Alexandr Stelnykovych
2025-05-07 17:36:37 +03:00
committed by GitHub

View File

@@ -107,15 +107,21 @@ func (tr *TCPResolver) UseTLS() *TCPResolver {
}
func (tr *TCPResolver) getOrCreateResolverConn(ctx context.Context) (*tcpResolverConn, error) {
var existingConn *tcpResolverConn
// Minimize the time we hold the lock to avoid blocking other threads.
tr.Lock()
defer tr.Unlock()
if tr.resolverConn != nil && tr.resolverConn.abandoned.IsNotSet() {
existingConn = tr.resolverConn
}
tr.Unlock()
// Check if we have a resolver.
if tr.resolverConn != nil && tr.resolverConn.abandoned.IsNotSet() {
if existingConn != nil {
// If there is one, check if it's alive!
select {
case tr.resolverConn.heartbeat <- struct{}{}:
return tr.resolverConn, nil
case existingConn.heartbeat <- struct{}{}:
return existingConn, nil
case <-time.After(heartbeatTimeout):
log.Warningf("resolver: heartbeat for dns client %s failed", tr.resolver.Info.DescriptiveName())
case <-ctx.Done():
@@ -162,6 +168,10 @@ func (tr *TCPResolver) getOrCreateResolverConn(ctx context.Context) (*tcpResolve
tr.resolver.Info.DescriptiveName(),
)
// Thread-safe resolverConn creation.
tr.Lock()
defer tr.Unlock()
// Create resolver connection.
tr.resolverConnInstanceID++
resolverConn := &tcpResolverConn{