mirror of
https://github.com/golang/go
synced 2024-11-20 02:14:46 -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>
99 lines
2.0 KiB
Go
99 lines
2.0 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 linux
|
|
|
|
package runtime
|
|
|
|
import "unsafe"
|
|
|
|
func epollcreate(size int32) int32
|
|
func epollcreate1(flags int32) int32
|
|
|
|
//go:noescape
|
|
func epollctl(epfd, op, fd int32, ev *epollevent) int32
|
|
|
|
//go:noescape
|
|
func epollwait(epfd int32, ev *epollevent, nev, timeout int32) int32
|
|
func closeonexec(fd int32)
|
|
|
|
var (
|
|
epfd int32 = -1 // epoll descriptor
|
|
)
|
|
|
|
func netpollinit() {
|
|
epfd = epollcreate1(_EPOLL_CLOEXEC)
|
|
if epfd >= 0 {
|
|
return
|
|
}
|
|
epfd = epollcreate(1024)
|
|
if epfd >= 0 {
|
|
closeonexec(epfd)
|
|
return
|
|
}
|
|
println("netpollinit: failed to create epoll descriptor", -epfd)
|
|
throw("netpollinit: failed to create descriptor")
|
|
}
|
|
|
|
func netpollopen(fd uintptr, pd *pollDesc) int32 {
|
|
var ev epollevent
|
|
ev.events = _EPOLLIN | _EPOLLOUT | _EPOLLRDHUP | _EPOLLET
|
|
*(**pollDesc)(unsafe.Pointer(&ev.data)) = pd
|
|
return -epollctl(epfd, _EPOLL_CTL_ADD, int32(fd), &ev)
|
|
}
|
|
|
|
func netpollclose(fd uintptr) int32 {
|
|
var ev epollevent
|
|
return -epollctl(epfd, _EPOLL_CTL_DEL, int32(fd), &ev)
|
|
}
|
|
|
|
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 epfd == -1 {
|
|
return nil
|
|
}
|
|
waitms := int32(-1)
|
|
if !block {
|
|
waitms = 0
|
|
}
|
|
var events [128]epollevent
|
|
retry:
|
|
n := epollwait(epfd, &events[0], int32(len(events)), waitms)
|
|
if n < 0 {
|
|
if n != -_EINTR {
|
|
println("runtime: epollwait on fd", epfd, "failed with", -n)
|
|
throw("epollwait failed")
|
|
}
|
|
goto retry
|
|
}
|
|
var gp guintptr
|
|
for i := int32(0); i < n; i++ {
|
|
ev := &events[i]
|
|
if ev.events == 0 {
|
|
continue
|
|
}
|
|
var mode int32
|
|
if ev.events&(_EPOLLIN|_EPOLLRDHUP|_EPOLLHUP|_EPOLLERR) != 0 {
|
|
mode += 'r'
|
|
}
|
|
if ev.events&(_EPOLLOUT|_EPOLLHUP|_EPOLLERR) != 0 {
|
|
mode += 'w'
|
|
}
|
|
if mode != 0 {
|
|
pd := *(**pollDesc)(unsafe.Pointer(&ev.data))
|
|
|
|
netpollready(&gp, pd, mode)
|
|
}
|
|
}
|
|
if block && gp == 0 {
|
|
goto retry
|
|
}
|
|
return gp.ptr()
|
|
}
|