diff --git a/src/net/cgo_unix.go b/src/net/cgo_unix.go index 460817bdf6..a4455f45d4 100644 --- a/src/net/cgo_unix.go +++ b/src/net/cgo_unix.go @@ -41,18 +41,12 @@ func (eai addrinfoErrno) isAddrinfoErrno() {} // context is cancellable. It is intended for use with calls that don't support context // cancellation (cgo, syscalls). blocking func may still be running after this function finishes. // For the duration of the execution of the blocking function, the thread is 'acquired' using [acquireThread], -// blocking might not be executed when the context gets cancelled. +// blocking might not be executed when the context gets cancelled early. func doBlockingWithCtx[T any](ctx context.Context, lookupName string, blocking func() (T, error)) (T, error) { - if err := acquireThread(ctx); err != nil { - var zero T - return zero, &DNSError{ - Name: lookupName, - Err: mapErr(ctx.Err()).Error(), - IsTimeout: ctx.Err() == context.DeadlineExceeded, - } - } - if ctx.Done() == nil { + // Context is non-cancellable, so there is no need + // to handle the error from acquireThread. + acquireThread(ctx) defer releaseThread() return blocking() } @@ -64,6 +58,16 @@ func doBlockingWithCtx[T any](ctx context.Context, lookupName string, blocking f res := make(chan result, 1) go func() { + if err := acquireThread(ctx); err != nil { + res <- result{ + err: &DNSError{ + Name: lookupName, + Err: mapErr(err).Error(), + IsTimeout: err == context.DeadlineExceeded, + }, + } + return + } defer releaseThread() var r result r.res, r.err = blocking() @@ -114,7 +118,7 @@ func cgoLookupPort(ctx context.Context, network, service string) (port int, err *_C_ai_family(&hints) = _C_AF_INET6 } - return doBlockingWithCtx(ctx, network + "/" + service, func() (int, error) { + return doBlockingWithCtx(ctx, network+"/"+service, func() (int, error) { return cgoLookupServicePort(&hints, network, service) }) } diff --git a/src/net/lookup_windows.go b/src/net/lookup_windows.go index 82f90d0522..bf05aaaed9 100644 --- a/src/net/lookup_windows.go +++ b/src/net/lookup_windows.go @@ -55,7 +55,7 @@ func lookupProtocol(ctx context.Context, name string) (int, error) { ch := make(chan result) // unbuffered go func() { if err := acquireThread(ctx); err != nil { - ch <- result{err: err} + ch <- result{err: mapErr(err)} return } defer releaseThread() @@ -115,7 +115,11 @@ func (r *Resolver) lookupIP(ctx context.Context, network, name string) ([]IPAddr getaddr := func() ([]IPAddr, error) { if err := acquireThread(ctx); err != nil { - return nil, err + return nil, &DNSError{ + Name: name, + Err: mapErr(err).Error(), + IsTimeout: ctx.Err() == context.DeadlineExceeded, + } } defer releaseThread() hints := syscall.AddrinfoW{ @@ -207,7 +211,11 @@ func (r *Resolver) lookupPort(ctx context.Context, network, service string) (int // TODO(bradfitz): finish ctx plumbing. Nothing currently depends on this. if err := acquireThread(ctx); err != nil { - return 0, err + return 0, &DNSError{ + Name: network + "/" + service, + Err: mapErr(err).Error(), + IsTimeout: ctx.Err() == context.DeadlineExceeded, + } } defer releaseThread() @@ -272,7 +280,11 @@ func (r *Resolver) lookupCNAME(ctx context.Context, name string) (string, error) // TODO(bradfitz): finish ctx plumbing. Nothing currently depends on this. if err := acquireThread(ctx); err != nil { - return "", err + return "", &DNSError{ + Name: name, + Err: mapErr(err).Error(), + IsTimeout: ctx.Err() == context.DeadlineExceeded, + } } defer releaseThread() var rec *syscall.DNSRecord @@ -299,7 +311,11 @@ func (r *Resolver) lookupSRV(ctx context.Context, service, proto, name string) ( } // TODO(bradfitz): finish ctx plumbing. Nothing currently depends on this. if err := acquireThread(ctx); err != nil { - return "", nil, err + return "", nil, &DNSError{ + Name: name, + Err: mapErr(err).Error(), + IsTimeout: ctx.Err() == context.DeadlineExceeded, + } } defer releaseThread() var target string @@ -331,7 +347,11 @@ func (r *Resolver) lookupMX(ctx context.Context, name string) ([]*MX, error) { } // TODO(bradfitz): finish ctx plumbing. Nothing currently depends on this. if err := acquireThread(ctx); err != nil { - return nil, err + return nil, &DNSError{ + Name: name, + Err: mapErr(err).Error(), + IsTimeout: ctx.Err() == context.DeadlineExceeded, + } } defer releaseThread() var rec *syscall.DNSRecord @@ -357,7 +377,11 @@ func (r *Resolver) lookupNS(ctx context.Context, name string) ([]*NS, error) { } // TODO(bradfitz): finish ctx plumbing. Nothing currently depends on this. if err := acquireThread(ctx); err != nil { - return nil, err + return nil, &DNSError{ + Name: name, + Err: mapErr(err).Error(), + IsTimeout: ctx.Err() == context.DeadlineExceeded, + } } defer releaseThread() var rec *syscall.DNSRecord @@ -382,7 +406,11 @@ func (r *Resolver) lookupTXT(ctx context.Context, name string) ([]string, error) } // TODO(bradfitz): finish ctx plumbing. Nothing currently depends on this. if err := acquireThread(ctx); err != nil { - return nil, err + return nil, &DNSError{ + Name: name, + Err: mapErr(err).Error(), + IsTimeout: ctx.Err() == context.DeadlineExceeded, + } } defer releaseThread() var rec *syscall.DNSRecord @@ -412,7 +440,11 @@ func (r *Resolver) lookupAddr(ctx context.Context, addr string) ([]string, error // TODO(bradfitz): finish ctx plumbing. Nothing currently depends on this. if err := acquireThread(ctx); err != nil { - return nil, err + return nil, &DNSError{ + Name: addr, + Err: mapErr(err).Error(), + IsTimeout: ctx.Err() == context.DeadlineExceeded, + } } defer releaseThread() arpa, err := reverseaddr(addr) diff --git a/src/net/net.go b/src/net/net.go index aa4335aa72..1758f15832 100644 --- a/src/net/net.go +++ b/src/net/net.go @@ -731,7 +731,7 @@ func acquireThread(ctx context.Context) error { case threadLimit <- struct{}{}: return nil case <-ctx.Done(): - return mapErr(ctx.Err()) + return ctx.Err() } }