mirror of
https://github.com/golang/go
synced 2024-11-20 03:34:40 -07:00
b6d115a583
The current code prints an error message and then tries to carry on. This is not helpful for Go users: they see a message that means nothing and that they can do nothing about. In the only known case of this message, in issue 11498, the best guess is that the netpoll code went into an infinite loop. Instead of doing that, crash the program. Fixes #11498. Change-Id: Idda3456c5b708f0df6a6b56c5bb4e796bbc39d7c Reviewed-on: https://go-review.googlesource.com/12047 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Reviewed-by: Dmitry Vyukov <dvyukov@google.com>
102 lines
2.2 KiB
Go
102 lines
2.2 KiB
Go
// Copyright 2013 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 darwin dragonfly freebsd netbsd openbsd
|
|
|
|
package runtime
|
|
|
|
// Integrated network poller (kqueue-based implementation).
|
|
|
|
import "unsafe"
|
|
|
|
func kqueue() int32
|
|
|
|
//go:noescape
|
|
func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32
|
|
func closeonexec(fd int32)
|
|
|
|
var (
|
|
kq int32 = -1
|
|
)
|
|
|
|
func netpollinit() {
|
|
kq = kqueue()
|
|
if kq < 0 {
|
|
println("netpollinit: kqueue failed with", -kq)
|
|
throw("netpollinit: kqueue failed")
|
|
}
|
|
closeonexec(kq)
|
|
}
|
|
|
|
func netpollopen(fd uintptr, pd *pollDesc) int32 {
|
|
// Arm both EVFILT_READ and EVFILT_WRITE in edge-triggered mode (EV_CLEAR)
|
|
// for the whole fd lifetime. The notifications are automatically unregistered
|
|
// when fd is closed.
|
|
var ev [2]keventt
|
|
*(*uintptr)(unsafe.Pointer(&ev[0].ident)) = fd
|
|
ev[0].filter = _EVFILT_READ
|
|
ev[0].flags = _EV_ADD | _EV_CLEAR
|
|
ev[0].fflags = 0
|
|
ev[0].data = 0
|
|
ev[0].udata = (*byte)(unsafe.Pointer(pd))
|
|
ev[1] = ev[0]
|
|
ev[1].filter = _EVFILT_WRITE
|
|
n := kevent(kq, &ev[0], 2, nil, 0, nil)
|
|
if n < 0 {
|
|
return -n
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func netpollclose(fd uintptr) int32 {
|
|
// Don't need to unregister because calling close()
|
|
// on fd will remove any kevents that reference the descriptor.
|
|
return 0
|
|
}
|
|
|
|
func netpollarm(pd *pollDesc, mode int) {
|
|
throw("unused")
|
|
}
|
|
|
|
// Polls for ready network connections.
|
|
// Returns list of goroutines that become runnable.
|
|
func netpoll(block bool) *g {
|
|
if kq == -1 {
|
|
return nil
|
|
}
|
|
var tp *timespec
|
|
var ts timespec
|
|
if !block {
|
|
tp = &ts
|
|
}
|
|
var events [64]keventt
|
|
retry:
|
|
n := kevent(kq, nil, 0, &events[0], int32(len(events)), tp)
|
|
if n < 0 {
|
|
if n != -_EINTR {
|
|
println("runtime: kevent on fd", kq, "failed with", -n)
|
|
throw("kevent failed")
|
|
}
|
|
goto retry
|
|
}
|
|
var gp guintptr
|
|
for i := 0; i < int(n); i++ {
|
|
ev := &events[i]
|
|
var mode int32
|
|
if ev.filter == _EVFILT_READ {
|
|
mode += 'r'
|
|
}
|
|
if ev.filter == _EVFILT_WRITE {
|
|
mode += 'w'
|
|
}
|
|
if mode != 0 {
|
|
netpollready(&gp, (*pollDesc)(unsafe.Pointer(ev.udata)), mode)
|
|
}
|
|
}
|
|
if block && gp == 0 {
|
|
goto retry
|
|
}
|
|
return gp.ptr()
|
|
}
|