net: fix deadlock in lookupProtocol on Windows

If the context expires before acquireThread(ctx) succeeds, then the
goroutine can block like:

net.lookupProtocol.func1()
	src/net/lookup_windows.go:58 +0x105
created by net.lookupProtocol in goroutine 2834
	src/net/lookup_windows.go:56 +0xda

We saw this in our UTs with a leak detector, confirmed by inspection of the
source code.
This commit is contained in:
Spike Curtis 2025-04-14 11:12:03 +04:00
parent 13b7c7d8d2
commit 27af7477a9

View file

@ -52,7 +52,7 @@ func lookupProtocol(ctx context.Context, name string) (int, error) {
proto int
err error
}
ch := make(chan result) // unbuffered
ch := make(chan result, 1) // buffer so that next goroutine never blocks
go func() {
if err := acquireThread(ctx); err != nil {
ch <- result{err: mapErr(err)}
@ -62,10 +62,7 @@ func lookupProtocol(ctx context.Context, name string) (int, error) {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
proto, err := getprotobyname(name)
select {
case ch <- result{proto: proto, err: err}:
case <-ctx.Done():
}
ch <- result{proto: proto, err: err}
}()
select {
case r := <-ch: