@@ -395,23 +395,30 @@ type PreflightE2EResult struct {
395395
396396// PreflightE2E runs a single e2e tunnel test against known-good resolvers
397397// to verify that the dnstt-server is reachable before scanning thousands of IPs.
398- // It tries preflightResolvers in order and returns on the first success.
398+ // It tries up to 3 resolvers with the full timeout, then stops.
399+ // This avoids waiting 18×20s if the server is actually down.
399400func PreflightE2E (bin , domain , pubkey , testURL , proxyAuth string , timeout time.Duration ) PreflightE2EResult {
400401 if testURL == "" {
401402 testURL = defaultTestURL
402403 }
403404 port := 29999 // dedicated port for preflight, outside normal pool range
404405
405- for _ , resolver := range preflightResolvers {
406- result := preflightSingle (bin , resolver , domain , pubkey , testURL , proxyAuth , port , timeout )
407- if result .OK {
408- return result
406+ maxAttempts := 3
407+ if maxAttempts > len (preflightResolvers ) {
408+ maxAttempts = len (preflightResolvers )
409+ }
410+
411+ var lastResult PreflightE2EResult
412+ for i := 0 ; i < maxAttempts ; i ++ {
413+ lastResult = preflightSingle (bin , preflightResolvers [i ], domain , pubkey , testURL , proxyAuth , port , timeout )
414+ if lastResult .OK {
415+ return lastResult
409416 }
410417 }
411418
412419 return PreflightE2EResult {
413420 OK : false ,
414- Err : fmt .Sprintf ("tunnel test failed via all preflight resolvers (%v) — dnstt-server may not be running or is misconfigured" , preflightResolvers ),
421+ Err : fmt .Sprintf ("tunnel test failed via %d resolvers — dnstt-server may not be running or is misconfigured" , maxAttempts ),
415422 }
416423}
417424
@@ -438,24 +445,22 @@ func preflightSingle(bin, resolver, domain, pubkey, testURL, proxyAuth string, p
438445 close (exited )
439446 }()
440447
441- defer func () {
448+ // cleanup: kill process and wait for exit before returning
449+ cleanup := func () {
442450 cmd .Process .Kill ()
443451 select {
444452 case <- exited :
445453 case <- time .After (2 * time .Second ):
446454 }
447- }()
455+ }
448456
449457 if waitAndTestSOCKS (ctx , port , testURL , proxyAuth , exited , timeout ) {
458+ cleanup ()
450459 return PreflightE2EResult {OK : true , Resolver : resolver }
451460 }
452461
453462 // Kill and wait to safely read stderr
454- cmd .Process .Kill ()
455- select {
456- case <- exited :
457- case <- time .After (2 * time .Second ):
458- }
463+ cleanup ()
459464 stderr := strings .TrimSpace (stderrBuf .String ())
460465 if stderr != "" {
461466 return PreflightE2EResult {Resolver : resolver , Stderr : truncate (stderr , 300 ), Err : "dnstt-client error: " + truncate (stderr , 200 )}
0 commit comments