internal/net: enforce timeout for probing stack

On Windows host with StarLink network, ctrld hangs on startup for ~30s
before continue running. This dues to IPv6 is configured but no external
IPv6 can be reached. When probing stack, ctrld is dialing using ipv6
without any timeout set, so the dialing timeout is enforced by OS.

This commit adds a timeout for probing dialer, so we ensure the probing
process will fail fast.
This commit is contained in:
Cuong Manh Le
2023-03-15 10:33:37 +07:00
committed by Cuong Manh Le
parent 3e6f6cc721
commit 096e7ea429
2 changed files with 34 additions and 3 deletions

View File

@@ -28,6 +28,13 @@ var Dialer = &net.Dialer{
},
}
const probeStackTimeout = 2 * time.Second
var probeStackDialer = &net.Dialer{
Resolver: Dialer.Resolver,
Timeout: probeStackTimeout,
}
var (
stackOnce atomic.Pointer[sync.Once]
ipv4Enabled bool
@@ -41,12 +48,12 @@ func init() {
}
func supportIPv4() bool {
_, err := Dialer.Dial("tcp4", net.JoinHostPort(controldIPv4Test, "80"))
_, err := probeStackDialer.Dial("tcp4", net.JoinHostPort(controldIPv4Test, "80"))
return err == nil
}
func supportIPv6(ctx context.Context) bool {
_, err := Dialer.DialContext(ctx, "tcp6", net.JoinHostPort(controldIPv6Test, "80"))
_, err := probeStackDialer.DialContext(ctx, "tcp6", net.JoinHostPort(controldIPv6Test, "80"))
return err == nil
}
@@ -61,7 +68,7 @@ func supportListenIPv6Local() bool {
func probeStack() {
b := backoff.NewBackoff("probeStack", func(format string, args ...any) {}, time.Minute)
for {
if _, err := Dialer.Dial("udp", bootstrapDNS); err == nil {
if _, err := probeStackDialer.Dial("udp", bootstrapDNS); err == nil {
hasNetworkUp = true
break
} else {

24
internal/net/net_test.go Normal file
View File

@@ -0,0 +1,24 @@
package net
import (
"context"
"testing"
"time"
)
func TestProbeStackTimeout(t *testing.T) {
done := make(chan struct{})
started := make(chan struct{})
go func() {
defer close(done)
close(started)
supportIPv6(context.Background())
}()
<-started
select {
case <-time.After(probeStackTimeout + time.Second):
t.Error("probeStack timeout is not enforce")
case <-done:
}
}