]> Cypherpunks repositories - gostls13.git/commitdiff
net: do not use RLock around Accept
authorRuss Cox <rsc@golang.org>
Fri, 8 Feb 2013 03:45:12 +0000 (22:45 -0500)
committerRuss Cox <rsc@golang.org>
Fri, 8 Feb 2013 03:45:12 +0000 (22:45 -0500)
It might be non-blocking, but it also might be blocking.
Cannot take the chance, as Accept might block indefinitely
and make it impossible to acquire ForkLock exclusively
(during fork+exec).

Fixes #4737.

R=golang-dev, dave, iant, mikioh.mikioh
CC=golang-dev
https://golang.org/cl/7309050

src/pkg/net/fd_unix.go
src/pkg/net/sock_cloexec.go
src/pkg/net/sys_cloexec.go

index a97674267c5634cd42cdff8f99937b50a22acdd1..9f710e2376f9b0e1db1e9f077e4d34087d1ae8dd 100644 (file)
@@ -661,6 +661,9 @@ func (fd *netFD) dup() (f *os.File, err error) {
        syscall.ForkLock.RUnlock()
 
        // We want blocking mode for the new fd, hence the double negative.
+       // This also puts the old fd into blocking mode, meaning that
+       // I/O will block the thread instead of letting us use the epoll server.
+       // Everything will still work, just with more threads.
        if err = syscall.SetNonblock(ns, false); err != nil {
                return nil, &OpError{"setnonblock", fd.net, fd.laddr, err}
        }
index e2a5ef7160a9243a78c43a1ec2a1db92cf954b24..12d0f34887c8a45ec8325fcb08f15fa1e723585c 100644 (file)
@@ -50,14 +50,14 @@ func accept(fd int) (int, syscall.Sockaddr, error) {
        }
 
        // See ../syscall/exec_unix.go for description of ForkLock.
-       // It is okay to hold the lock across syscall.Accept
+       // It is probably okay to hold the lock across syscall.Accept
        // because we have put fd.sysfd into non-blocking mode.
-       syscall.ForkLock.RLock()
+       // However, a call to the File method will put it back into
+       // blocking mode. We can't take that risk, so no use of ForkLock here.
        nfd, sa, err = syscall.Accept(fd)
        if err == nil {
                syscall.CloseOnExec(nfd)
        }
-       syscall.ForkLock.RUnlock()
        if err != nil {
                return -1, nil, err
        }
index 75d5688a163af10333d79f7385efe4115fcf6911..17e8749087df2f41c32e47dbef9a139f899fdddb 100644 (file)
@@ -35,14 +35,14 @@ func sysSocket(f, t, p int) (int, error) {
 // descriptor as nonblocking and close-on-exec.
 func accept(fd int) (int, syscall.Sockaddr, error) {
        // See ../syscall/exec_unix.go for description of ForkLock.
-       // It is okay to hold the lock across syscall.Accept
+       // It is probably okay to hold the lock across syscall.Accept
        // because we have put fd.sysfd into non-blocking mode.
-       syscall.ForkLock.RLock()
+       // However, a call to the File method will put it back into
+       // blocking mode. We can't take that risk, so no use of ForkLock here.
        nfd, sa, err := syscall.Accept(fd)
        if err == nil {
                syscall.CloseOnExec(nfd)
        }
-       syscall.ForkLock.RUnlock()
        if err != nil {
                return -1, nil, err
        }