re PR go/52583 (Several new go testsuite failues on Solaris)

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.

From-SVN: r186801
This commit is contained in:
Ian Lance Taylor 2012-04-25 04:26:12 +00:00
parent b427dd7ae3
commit b685de12d2
7 changed files with 166 additions and 9 deletions

View 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

View 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

View 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

View 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 {

View 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":

View File

@ -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
}

View File

@ -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
}