sys: Work around nil references in Select.

This fixes #612.
This commit is contained in:
Qi Xiao 2018-03-01 13:53:12 -05:00
parent 7a4ebd1306
commit 9865e3c0c8
6 changed files with 34 additions and 32 deletions

View File

@ -8,15 +8,16 @@ package sys
import (
"reflect"
"syscall"
"golang.org/x/sys/unix"
)
var nFdBits = (uint)(reflect.TypeOf(syscall.FdSet{}.X__fds_bits[0]).Size() * 8)
var nFdBits = (uint)(reflect.TypeOf(unix.FdSet{}.X__fds_bits[0]).Size() * 8)
type FdSet syscall.FdSet
type FdSet unix.FdSet
func (fs *FdSet) s() *syscall.FdSet {
return (*syscall.FdSet)(fs)
func (fs *FdSet) s() *unix.FdSet {
return (*unix.FdSet)(fs)
}
func NewFdSet(fds ...int) *FdSet {

View File

@ -3,16 +3,17 @@
package sys
import (
"syscall"
"unsafe"
"golang.org/x/sys/unix"
)
var nFdBits = uint(8 * unsafe.Sizeof(syscall.FdSet{}.Bits[0]))
var nFdBits = uint(8 * unsafe.Sizeof(unix.FdSet{}.Bits[0]))
type FdSet syscall.FdSet
type FdSet unix.FdSet
func (fs *FdSet) s() *syscall.FdSet {
return (*syscall.FdSet)(fs)
func (fs *FdSet) s() *unix.FdSet {
return (*unix.FdSet)(fs)
}
func NewFdSet(fds ...int) *FdSet {

View File

@ -2,8 +2,8 @@
package sys
import "syscall"
import "golang.org/x/sys/unix"
func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *syscall.Timeval) (err error) {
return syscall.Select(nfd, r.s(), w.s(), e.s(), timeout)
func Select(nfd int, r *FdSet, w *FdSet, e *FdSet) error {
return unix.Select(nfd, r.s(), w.s(), e.s(), nil)
}

View File

@ -2,13 +2,12 @@
package sys
import "syscall"
import "golang.org/x/sys/unix"
func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *syscall.Timeval) error {
// On ARM64, MIPS64 and MIPS64LE, syscall.Select is emulated in userland and
// will dereference timeout. In that case, if the timeout argument is nil,
// the call will panic. This is not POSIX-conformant behavior, but we work
// around this by supplying a default value for timeout.
_, err := syscall.Select(nfd, r.s(), w.s(), e.s(), timeout)
func Select(nfd int, r *FdSet, w *FdSet, e *FdSet) error {
// On ARM64, MIPS64 and MIPS64LE, unix.Select is emulated in userland and
// will dereference timeout. In that case, we use Pselect to work around the
// problem. Bug: https://github.com/golang/go/issues/24189
_, err := unix.Pselect(nfd, r.s(), w.s(), e.s(), nil, nil)
return err
}

View File

@ -3,8 +3,9 @@
package sys
import (
"syscall"
"testing"
"golang.org/x/sys/unix"
)
func TestFdSet(t *testing.T) {
@ -30,8 +31,8 @@ func TestFdSet(t *testing.T) {
func TestSelect(t *testing.T) {
var p1, p2 [2]int
mustNil(syscall.Pipe(p1[:]))
mustNil(syscall.Pipe(p2[:]))
mustNil(unix.Pipe(p1[:]))
mustNil(unix.Pipe(p2[:]))
fs := NewFdSet(p1[0], p2[0])
var maxfd int
if p1[0] > p2[0] {
@ -40,16 +41,16 @@ func TestSelect(t *testing.T) {
maxfd = p2[0] + 1
}
go func() {
syscall.Write(p1[1], []byte("to p1"))
syscall.Write(p2[1], []byte("to p2"))
syscall.Close(p1[1])
syscall.Close(p2[1])
unix.Write(p1[1], []byte("to p1"))
unix.Write(p2[1], []byte("to p2"))
unix.Close(p1[1])
unix.Close(p2[1])
}()
e := Select(maxfd+1, fs, nil, nil, nil)
e := Select(maxfd+1, fs, nil, nil)
if e != nil {
t.Errorf("Select(%v, %v, nil, nil, nil) => %v, want <nil>",
t.Errorf("Select(%v, %v, nil, nil) => %v, want <nil>",
maxfd+1, fs, e)
}
syscall.Close(p1[0])
syscall.Close(p2[0])
unix.Close(p1[0])
unix.Close(p2[0])
}

View File

@ -20,7 +20,7 @@ func WaitForRead(files ...*os.File) (ready []bool, err error) {
}
fdset.Set(fd)
}
err = Select(maxfd+1, fdset, nil, nil, nil)
err = Select(maxfd+1, fdset, nil, nil)
ready = make([]bool, len(files))
for i, file := range files {
ready[i] = fdset.IsSet(int(file.Fd()))