This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]