Просмотр исходного кода

unix: fix Select to return number of ready fds on Solaris

Make Select's signature on Solaris match the one on Linux and return the number
of ready file descriptors.

Updates golang/go#34458

Change-Id: I118c4c35cbc83dba015ef357ce9bef44c9165ec1
Reviewed-on: https://go-review.googlesource.com/c/sys/+/196807
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Tobias Klauser 6 лет назад
Родитель
Сommit
e2fefa8ec2

+ 1 - 0
unix/mkerrors.sh

@@ -348,6 +348,7 @@ includes_OpenBSD='
 includes_SunOS='
 #include <limits.h>
 #include <sys/types.h>
+#include <sys/select.h>
 #include <sys/socket.h>
 #include <sys/sockio.h>
 #include <sys/stat.h>

+ 1 - 1
unix/syscall_solaris.go

@@ -649,7 +649,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
 //sys	Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
 //sys	Rmdir(path string) (err error)
 //sys	Seek(fd int, offset int64, whence int) (newoffset int64, err error) = lseek
-//sys	Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error)
+//sys	Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
 //sysnb	Setegid(egid int) (err error)
 //sysnb	Seteuid(euid int) (err error)
 //sysnb	Setgid(gid int) (err error)

+ 33 - 2
unix/syscall_solaris_test.go

@@ -7,6 +7,7 @@
 package unix_test
 
 import (
+	"os"
 	"os/exec"
 	"testing"
 	"time"
@@ -15,23 +16,53 @@ import (
 )
 
 func TestSelect(t *testing.T) {
-	err := unix.Select(0, nil, nil, nil, &unix.Timeval{Sec: 0, Usec: 0})
+	n, err := unix.Select(0, nil, nil, nil, &unix.Timeval{Sec: 0, Usec: 0})
 	if err != nil {
 		t.Fatalf("Select: %v", err)
 	}
+	if n != 0 {
+		t.Fatalf("Select: expected 0 ready file descriptors, got %v", n)
+	}
 
 	dur := 150 * time.Millisecond
 	tv := unix.NsecToTimeval(int64(dur))
 	start := time.Now()
-	err = unix.Select(0, nil, nil, nil, &tv)
+	n, err = unix.Select(0, nil, nil, nil, &tv)
 	took := time.Since(start)
 	if err != nil {
 		t.Fatalf("Select: %v", err)
 	}
+	if n != 0 {
+		t.Fatalf("Select: expected 0 ready file descriptors, got %v", n)
+	}
 
 	if took < dur {
 		t.Errorf("Select: timeout should have been at least %v, got %v", dur, took)
 	}
+
+	rr, ww, err := os.Pipe()
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer rr.Close()
+	defer ww.Close()
+
+	if _, err := ww.Write([]byte("HELLO GOPHER")); err != nil {
+		t.Fatal(err)
+	}
+
+	rFdSet := &unix.FdSet{}
+	fd := rr.Fd()
+	// FD_SET(fd, rFdSet)
+	rFdSet.Bits[fd/unix.NFDBITS] |= (1 << (fd % unix.NFDBITS))
+
+	n, err = unix.Select(int(fd+1), rFdSet, nil, nil, nil)
+	if err != nil {
+		t.Fatalf("Select: %v", err)
+	}
+	if n != 1 {
+		t.Fatalf("Select: expected 1 ready file descriptors, got %v", n)
+	}
 }
 
 func TestStatvfs(t *testing.T) {

+ 2 - 1
unix/zerrors_solaris_amd64.go

@@ -3,7 +3,7 @@
 
 // +build amd64,solaris
 
-// Created by cgo -godefs - DO NOT EDIT
+// Code generated by cmd/cgo -godefs; DO NOT EDIT.
 // cgo -godefs -- -m64 _const.go
 
 package unix
@@ -666,6 +666,7 @@ const (
 	M_FLUSH                       = 0x86
 	NAME_MAX                      = 0xff
 	NEWDEV                        = 0x1
+	NFDBITS                       = 0x40
 	NL0                           = 0x0
 	NL1                           = 0x100
 	NLDLY                         = 0x100

+ 3 - 2
unix/zsyscall_solaris_amd64.go

@@ -1478,8 +1478,9 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) {
-	_, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procSelect)), 5, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0)
+func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) {
+	r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procSelect)), 5, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0)
+	n = int(r0)
 	if e1 != 0 {
 		err = e1
 	}