mirror of
https://github.com/slackhq/nebula.git
synced 2026-08-15 15:37:03 +02:00
more fixes!
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
//go:build linux && !android
|
||||
// +build linux,!android
|
||||
|
||||
package tio
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// blockOn parks the calling goroutine until fd is ready (events is POLLIN for
|
||||
// reads, POLLOUT for writes) or shutdownFd signals teardown. It builds the
|
||||
// pollfd array on the stack every call, so concurrent callers on the same
|
||||
// Queue never share Revents storage: the previous shared-array implementation
|
||||
// was a genuine Go data race when two writers parked in poll(2) at once (the
|
||||
// kernel writing Revents while another goroutine zeroed it). Level-triggered
|
||||
// events kept it from deadlocking, but it was still a race.
|
||||
//
|
||||
// Poll(2) is looped over EINTR. err is checked before the Revents bits are
|
||||
// trusted, since a failed poll may leave them bogus. Returns os.ErrClosed when
|
||||
// shutdown was signaled (POLLIN on shutdownFd) or either fd reported a problem
|
||||
// condition (POLLHUP|POLLNVAL|POLLERR).
|
||||
func blockOn(fd, shutdownFd int32, events int16) error {
|
||||
const problemFlags = unix.POLLHUP | unix.POLLNVAL | unix.POLLERR
|
||||
pfds := [2]unix.PollFd{
|
||||
{Fd: fd, Events: events},
|
||||
{Fd: shutdownFd, Events: unix.POLLIN},
|
||||
}
|
||||
var err error
|
||||
for {
|
||||
_, err = unix.Poll(pfds[:], -1)
|
||||
if err != unix.EINTR {
|
||||
break
|
||||
}
|
||||
}
|
||||
tunEvents := pfds[0].Revents
|
||||
shutdownEvents := pfds[1].Revents
|
||||
// Check err before trusting the potentially bogus bits we just got.
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if shutdownEvents&(unix.POLLIN|problemFlags) != 0 {
|
||||
return os.ErrClosed
|
||||
}
|
||||
if tunEvents&problemFlags != 0 {
|
||||
return os.ErrClosed
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user