DHT Deadlockfix
Some checks are pending
CI Pipeline / Run Tests (push) Waiting to run
CI Pipeline / Lint Code (push) Waiting to run
CI Pipeline / Security Scan (push) Waiting to run
CI Pipeline / E2E Tests (push) Blocked by required conditions

This commit is contained in:
Enki 2025-09-02 19:29:45 -07:00
parent 8f485829f7
commit 2b7f44b2d7
3 changed files with 46 additions and 14 deletions

View File

@ -1,6 +1,7 @@
package dht package dht
import ( import (
"context"
"crypto/rand" "crypto/rand"
"crypto/sha1" "crypto/sha1"
"database/sql" "database/sql"
@ -2217,41 +2218,67 @@ func (d *DHT) queryNodesParallel(candidates []*Node, targetID NodeID, queryType
resultChan := make(chan queryResult, len(candidates)) resultChan := make(chan queryResult, len(candidates))
var wg sync.WaitGroup var wg sync.WaitGroup
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
// Launch parallel queries // Launch parallel queries
for _, candidate := range candidates { for _, candidate := range candidates {
wg.Add(1) wg.Add(1)
go func(node *Node) { go func(node *Node) {
defer wg.Done() defer func() {
if r := recover(); r != nil {
log.Printf("DHT query panic recovered: %v", r)
}
wg.Done()
}()
key := fmt.Sprintf("%s:%d", node.Addr.IP, node.Addr.Port) key := fmt.Sprintf("%s:%d", node.Addr.IP, node.Addr.Port)
queried[key] = true queried[key] = true
var discoveredNodes []*Node var discoveredNodes []*Node
if queryType == "find_node" { select {
nodes, err := d.FindNode(targetID, node.Addr) case <-ctx.Done():
if err == nil { return
discoveredNodes = nodes default:
if queryType == "find_node" {
nodes, err := d.FindNode(targetID, node.Addr)
if err == nil {
discoveredNodes = nodes
}
} else if queryType == "get_peers" {
_, nodes, err := d.GetPeers(targetID[:], node.Addr)
if err == nil && nodes != nil {
discoveredNodes = nodes
}
} }
} else if queryType == "get_peers" {
_, nodes, err := d.GetPeers(targetID[:], node.Addr) select {
if err == nil && nodes != nil { case resultChan <- queryResult{nodes: discoveredNodes, node: node}:
discoveredNodes = nodes case <-ctx.Done():
return
} }
} }
resultChan <- queryResult{nodes: discoveredNodes, node: node}
}(candidate) }(candidate)
} }
// Close channel when all queries complete // Close channel when all queries complete or timeout
go func() { go func() {
wg.Wait() done := make(chan struct{})
go func() {
defer close(done)
wg.Wait()
}()
select {
case <-done:
case <-ctx.Done():
log.Printf("DHT parallel query timeout after 30s")
}
close(resultChan) close(resultChan)
}() }()
// Collect results // Collect results with timeout
var allNodes []*Node var allNodes []*Node
for result := range resultChan { for result := range resultChan {
if len(result.nodes) > 0 { if len(result.nodes) > 0 {

View File

@ -107,6 +107,11 @@ func NewUnifiedP2PGateway(config *config.Config, db *sql.DB) *UnifiedP2PGateway
func (g *UnifiedP2PGateway) Initialize() error { func (g *UnifiedP2PGateway) Initialize() error {
log.Printf("P2P Gateway: Initializing unified P2P system") log.Printf("P2P Gateway: Initializing unified P2P system")
// Create database tables
if err := g.CreateP2PTables(); err != nil {
return fmt.Errorf("failed to create P2P database tables: %w", err)
}
// Initialize tracker // Initialize tracker
if err := g.initializeTracker(); err != nil { if err := g.initializeTracker(); err != nil {
return fmt.Errorf("failed to initialize tracker: %w", err) return fmt.Errorf("failed to initialize tracker: %w", err)

Binary file not shown.