summaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2012-04-25 04:26:12 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2012-04-25 04:26:12 +0000
commitd41b42a65d5c90c8067cca069524f07350a44cb4 (patch)
treebb3c841696f0b436993d0d21e5041a2489adfb92 /libgo
parentcef20746448f8897180eed3a49a3f8c68b0147f2 (diff)
downloadgcc-d41b42a65d5c90c8067cca069524f07350a44cb4.tar.gz
PR go/52583
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/trunk@186801 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgo')
-rw-r--r--libgo/Makefile.am6
-rw-r--r--libgo/Makefile.in6
-rw-r--r--libgo/go/net/dial_test.go2
-rw-r--r--libgo/go/net/fd_select.go22
-rw-r--r--libgo/go/net/multicast_test.go2
-rw-r--r--libgo/go/net/sock_solaris.go47
-rw-r--r--libgo/go/net/sockoptip_solaris.go90
7 files changed, 166 insertions, 9 deletions
diff --git a/libgo/Makefile.am b/libgo/Makefile.am
index a56d2e885c2..074d66405cd 100644
--- a/libgo/Makefile.am
+++ b/libgo/Makefile.am
@@ -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
diff --git a/libgo/Makefile.in b/libgo/Makefile.in
index 32c5afcc51f..bbec292fb94 100644
--- a/libgo/Makefile.in
+++ b/libgo/Makefile.in
@@ -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
diff --git a/libgo/go/net/dial_test.go b/libgo/go/net/dial_test.go
index 7212087fe0c..63b91b37ead 100644
--- a/libgo/go/net/dial_test.go
+++ b/libgo/go/net/dial_test.go
@@ -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
diff --git a/libgo/go/net/fd_select.go b/libgo/go/net/fd_select.go
index 39c8f2777b2..22db1cbcac2 100644
--- a/libgo/go/net/fd_select.go
+++ b/libgo/go/net/fd_select.go
@@ -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 {
diff --git a/libgo/go/net/multicast_test.go b/libgo/go/net/multicast_test.go
index 67261b1ee77..50c0f0a82c9 100644
--- a/libgo/go/net/multicast_test.go
+++ b/libgo/go/net/multicast_test.go
@@ -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
index 00000000000..ad639cc4a7f
--- /dev/null
+++ b/libgo/go/net/sock_solaris.go
@@ -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
index 00000000000..538ef0d1179
--- /dev/null
+++ b/libgo/go/net/sockoptip_solaris.go
@@ -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
+}