From: Dmitriy Vyukov Date: Sun, 4 Aug 2013 19:31:23 +0000 (+0400) Subject: net: fix concurrent Accept on windows X-Git-Tag: go1.2rc2~798 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=77f21eea597f374e025497c167caccfd72864e13;p=gostls13.git net: fix concurrent Accept on windows Runtime netpoll supports at most one read waiter and at most one write waiter. It's responsibility of net package to ensure that. Currently windows implementation allows more than one waiter in Accept. It leads to "fatal error: netpollblock: double wait". R=golang-dev, bradfitz CC=golang-dev https://golang.org/cl/12400045 --- diff --git a/src/pkg/net/fd_windows.go b/src/pkg/net/fd_windows.go index 5d584621a7..f51d1616e0 100644 --- a/src/pkg/net/fd_windows.go +++ b/src/pkg/net/fd_windows.go @@ -579,6 +579,8 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) { } // Submit accept request. + fd.rio.Lock() + defer fd.rio.Unlock() var o acceptOp o.Init(fd, 'r') o.newsock = s diff --git a/src/pkg/net/tcp_test.go b/src/pkg/net/tcp_test.go index a71b02b477..f356f92f09 100644 --- a/src/pkg/net/tcp_test.go +++ b/src/pkg/net/tcp_test.go @@ -8,6 +8,7 @@ import ( "fmt" "reflect" "runtime" + "sync" "testing" "time" ) @@ -294,3 +295,35 @@ func TestIPv6LinkLocalUnicastTCP(t *testing.T) { <-done } } + +func TestTCPConcurrentAccept(t *testing.T) { + defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) + ln, err := Listen("tcp", "127.0.0.1:0") + if err != nil { + t.Fatalf("Listen failed: %v", err) + } + const N = 10 + var wg sync.WaitGroup + wg.Add(N) + for i := 0; i < N; i++ { + go func() { + for { + c, err := ln.Accept() + if err != nil { + break + } + c.Close() + } + wg.Done() + }() + } + for i := 0; i < 10*N; i++ { + c, err := Dial("tcp", ln.Addr().String()) + if err != nil { + t.Fatalf("Dial failed: %v", err) + } + c.Close() + } + ln.Close() + wg.Wait() +}