OSDN Git Service

PR go/52583
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 25 Apr 2012 04:26:31 +0000 (04:26 +0000)
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 25 Apr 2012 04:26:31 +0000 (04:26 +0000)
net: Solaris fixes.

In particular fix fd_select.go to handle the case where a file
descriptor is closed by one goroutine while another goroutine
is waiting for it.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_7-branch@186802 138bc75d-0d04-0410-961f-82ee72b054a4

libgo/Makefile.am
libgo/Makefile.in
libgo/go/net/dial_test.go
libgo/go/net/fd_select.go
libgo/go/net/multicast_test.go
libgo/go/net/sock_solaris.go [new file with mode: 0644]
libgo/go/net/sockoptip_solaris.go [new file with mode: 0644]

index a56d2e8..074d664 100644 (file)
@@ -654,9 +654,9 @@ go_net_sockoptip_file = go/net/sockoptip_linux.go
 else
 if LIBGO_IS_SOLARIS
 go_net_cgo_file = go/net/cgo_linux.go
-go_net_sock_file = go/net/sock_linux.go
-go_net_sockopt_file = go/net/sockopt_linux.go
-go_net_sockoptip_file = go/net/sockoptip_linux.go
+go_net_sock_file = go/net/sock_solaris.go
+go_net_sockopt_file = go/net/sockopt_bsd.go
+go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_solaris.go
 else
 if LIBGO_IS_FREEBSD
 go_net_cgo_file = go/net/cgo_bsd.go
index 32c5afc..bbec292 100644 (file)
@@ -1019,17 +1019,17 @@ go_mime_files = \
 @LIBGO_IS_LINUX_TRUE@go_net_cgo_file = go/net/cgo_linux.go
 @LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sock_file = go/net/sock_bsd.go
 @LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sock_file = go/net/sock_bsd.go
-@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_sock_file = go/net/sock_linux.go
+@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_sock_file = go/net/sock_solaris.go
 @LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_sock_file = go/net/sock_linux.go
 @LIBGO_IS_LINUX_TRUE@go_net_sock_file = go/net/sock_linux.go
 @LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sockopt_file = go/net/sockopt_bsd.go
 @LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sockopt_file = go/net/sockopt_bsd.go
-@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_sockopt_file = go/net/sockopt_linux.go
+@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_sockopt_file = go/net/sockopt_bsd.go
 @LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_sockopt_file = go/net/sockopt_linux.go
 @LIBGO_IS_LINUX_TRUE@go_net_sockopt_file = go/net/sockopt_linux.go
 @LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_netbsd.go
 @LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_freebsd.go
-@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_sockoptip_file = go/net/sockoptip_linux.go
+@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_solaris.go
 @LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_sockoptip_file = go/net/sockoptip_linux.go
 @LIBGO_IS_LINUX_TRUE@go_net_sockoptip_file = go/net/sockoptip_linux.go
 @LIBGO_IS_LINUX_FALSE@go_net_sendfile_file = go/net/sendfile_stub.go
index 7212087..63b91b3 100644 (file)
@@ -130,7 +130,7 @@ func TestSelfConnect(t *testing.T) {
                n = 1000
        }
        switch runtime.GOOS {
-       case "darwin", "freebsd", "openbsd", "windows":
+       case "darwin", "freebsd", "openbsd", "solaris", "windows":
                // Non-Linux systems take a long time to figure
                // out that there is nothing listening on localhost.
                n = 100
index 39c8f27..22db1cb 100644 (file)
@@ -102,7 +102,27 @@ func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err erro
                                break
                        }
                }
-               if e != nil {
+               if e == syscall.EBADF {
+                       // Some file descriptor has been closed.
+                       tmpReadFds = syscall.FdSet{}
+                       tmpWriteFds = syscall.FdSet{}
+                       n = 0
+                       for i := 0; i < p.maxFd+1; i++ {
+                               if syscall.FDIsSet(i, p.readFds) {
+                                       var s syscall.Stat_t
+                                       if syscall.Fstat(i, &s) == syscall.EBADF {
+                                               syscall.FDSet(i, &tmpReadFds)
+                                               n++
+                                       }
+                               } else if syscall.FDIsSet(i, p.writeFds) {
+                                       var s syscall.Stat_t
+                                       if syscall.Fstat(i, &s) == syscall.EBADF {
+                                               syscall.FDSet(i, &tmpWriteFds)
+                                               n++
+                                       }
+                               }
+                       }
+               } else if e != nil {
                        return -1, 0, os.NewSyscallError("select", e)
                }
                if n == 0 {
index 67261b1..50c0f0a 100644 (file)
@@ -46,7 +46,7 @@ var multicastListenerTests = []struct {
 // listener with same address family, same group address and same port.
 func TestMulticastListener(t *testing.T) {
        switch runtime.GOOS {
-       case "netbsd", "openbsd", "plan9", "windows":
+       case "netbsd", "openbsd", "plan9", "solaris", "windows":
                t.Logf("skipping test on %q", runtime.GOOS)
                return
        case "linux":
diff --git a/libgo/go/net/sock_solaris.go b/libgo/go/net/sock_solaris.go
new file mode 100644 (file)
index 0000000..ad639cc
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build solaris
+
+// Sockets for Solaris
+
+package net
+
+import (
+       "syscall"
+)
+
+func maxListenerBacklog() int {
+       // The kernel does not track the limit.
+       return syscall.SOMAXCONN
+}
+
+func listenerSockaddr(s, f int, la syscall.Sockaddr, toAddr func(syscall.Sockaddr) Addr) (syscall.Sockaddr, error) {
+       a := toAddr(la)
+       if a == nil {
+               return la, nil
+       }
+       switch v := a.(type) {
+       case *TCPAddr, *UnixAddr:
+               err := setDefaultListenerSockopts(s)
+               if err != nil {
+                       return nil, err
+               }
+       case *UDPAddr:
+               if v.IP.IsMulticast() {
+                       err := setDefaultMulticastSockopts(s)
+                       if err != nil {
+                               return nil, err
+                       }
+                       switch f {
+                       case syscall.AF_INET:
+                               v.IP = IPv4zero
+                       case syscall.AF_INET6:
+                               v.IP = IPv6unspecified
+                       }
+                       return v.sockaddr(f)
+               }
+       }
+       return la, nil
+}
diff --git a/libgo/go/net/sockoptip_solaris.go b/libgo/go/net/sockoptip_solaris.go
new file mode 100644 (file)
index 0000000..538ef0d
--- /dev/null
@@ -0,0 +1,90 @@
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// IP-level socket options for Solaris
+
+package net
+
+import (
+       "os"
+       "syscall"
+)
+
+func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
+       if err := fd.incref(false); err != nil {
+               return nil, err
+       }
+       defer fd.decref()
+       a, err := syscall.GetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF)
+       if err != nil {
+               return nil, os.NewSyscallError("getsockopt", err)
+       }
+       return ipv4AddrToInterface(IPv4(a[0], a[1], a[2], a[3]))
+}
+
+func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
+       ip, err := interfaceToIPv4Addr(ifi)
+       if err != nil {
+               return os.NewSyscallError("setsockopt", err)
+       }
+       var x [4]byte
+       copy(x[:], ip.To4())
+       if err := fd.incref(false); err != nil {
+               return err
+       }
+       defer fd.decref()
+       err = syscall.SetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, x)
+       if err != nil {
+               return os.NewSyscallError("setsockopt", err)
+       }
+       return nil
+}
+
+func ipv4MulticastLoopback(fd *netFD) (bool, error) {
+       if err := fd.incref(false); err != nil {
+               return false, err
+       }
+       defer fd.decref()
+       v, err := syscall.GetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP)
+       if err != nil {
+               return false, os.NewSyscallError("getsockopt", err)
+       }
+       return v == 1, nil
+}
+
+func setIPv4MulticastLoopback(fd *netFD, v bool) error {
+       if err := fd.incref(false); err != nil {
+               return err
+       }
+       defer fd.decref()
+       err := syscall.SetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, byte(boolint(v)))
+       if err != nil {
+               return os.NewSyscallError("setsockopt", err)
+       }
+       return nil
+}
+
+func ipv4ReceiveInterface(fd *netFD) (bool, error) {
+       if err := fd.incref(false); err != nil {
+               return false, err
+       }
+       defer fd.decref()
+       v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF)
+       if err != nil {
+               return false, os.NewSyscallError("getsockopt", err)
+       }
+       return v == 1, nil
+}
+
+func setIPv4ReceiveInterface(fd *netFD, v bool) error {
+       if err := fd.incref(false); err != nil {
+               return err
+       }
+       defer fd.decref()
+       err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF, boolint(v))
+       if err != nil {
+               return os.NewSyscallError("setsockopt", err)
+       }
+       return nil
+}