diff options
author | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-04-25 04:26:12 +0000 |
---|---|---|
committer | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-04-25 04:26:12 +0000 |
commit | d41b42a65d5c90c8067cca069524f07350a44cb4 (patch) | |
tree | bb3c841696f0b436993d0d21e5041a2489adfb92 /libgo | |
parent | cef20746448f8897180eed3a49a3f8c68b0147f2 (diff) | |
download | gcc-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.am | 6 | ||||
-rw-r--r-- | libgo/Makefile.in | 6 | ||||
-rw-r--r-- | libgo/go/net/dial_test.go | 2 | ||||
-rw-r--r-- | libgo/go/net/fd_select.go | 22 | ||||
-rw-r--r-- | libgo/go/net/multicast_test.go | 2 | ||||
-rw-r--r-- | libgo/go/net/sock_solaris.go | 47 | ||||
-rw-r--r-- | libgo/go/net/sockoptip_solaris.go | 90 |
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 +} |