This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
libgo patch committed: Fix net package for Solaris
- From: Ian Lance Taylor <iant at google dot com>
- To: gcc-patches at gcc dot gnu dot org, gofrontend-dev at googlegroups dot com
- Date: Tue, 24 Apr 2012 21:26:58 -0700
- Subject: libgo patch committed: Fix net package for Solaris
This patch to libgo fixes the net package to work correctly on Solaris.
The main fix is to the select code, to fix the case where one goroutine
closes a file descriptor while another goroutine is waiting for I/O on
the descriptor. Bootstrapped and ran Go testsuite on
sparc-sun-solaris2.11. Committed to mainline and 4.7 branch.
Ian
diff -r 19c80c28161e libgo/Makefile.am
--- a/libgo/Makefile.am Tue Apr 24 13:11:46 2012 -0700
+++ b/libgo/Makefile.am Tue Apr 24 20:10:20 2012 -0700
@@ -654,9 +654,9 @@
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 -r 19c80c28161e libgo/Makefile.in
--- a/libgo/Makefile.in Tue Apr 24 13:11:46 2012 -0700
+++ b/libgo/Makefile.in Tue Apr 24 20:10:20 2012 -0700
@@ -1019,17 +1019,17 @@
@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 -r 19c80c28161e libgo/go/net/dial_test.go
--- a/libgo/go/net/dial_test.go Tue Apr 24 13:11:46 2012 -0700
+++ b/libgo/go/net/dial_test.go Tue Apr 24 20:10:20 2012 -0700
@@ -130,7 +130,7 @@
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 -r 19c80c28161e libgo/go/net/fd_select.go
--- a/libgo/go/net/fd_select.go Tue Apr 24 13:11:46 2012 -0700
+++ b/libgo/go/net/fd_select.go Tue Apr 24 20:10:20 2012 -0700
@@ -102,7 +102,27 @@
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 -r 19c80c28161e libgo/go/net/multicast_test.go
--- a/libgo/go/net/multicast_test.go Tue Apr 24 13:11:46 2012 -0700
+++ b/libgo/go/net/multicast_test.go Tue Apr 24 20:10:20 2012 -0700
@@ -46,7 +46,7 @@
// 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 -r 19c80c28161e libgo/go/net/sock_solaris.go
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libgo/go/net/sock_solaris.go Tue Apr 24 20:10:20 2012 -0700
@@ -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 -r 19c80c28161e libgo/go/net/sockoptip_solaris.go
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libgo/go/net/sockoptip_solaris.go Tue Apr 24 20:10:20 2012 -0700
@@ -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
+}