Skip to content

Commit

Permalink
gvisor/hostnet: restart epoll_wait after epoll_ctl
Browse files Browse the repository at this point in the history
Otherwise changes of epoll_ctl will not have affect.

PiperOrigin-RevId: 247964961
Change-Id: I9fbb35c44766421af45d9ed53760e0c324d80d99
  • Loading branch information
avagin authored and shentubot committed May 13, 2019
1 parent 9f2b12c commit ec248da
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 2 deletions.
30 changes: 28 additions & 2 deletions pkg/fdnotifier/fdnotifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ type notifier struct {
// notifications.
epFD int

// eventFD is used to restart epoll_wait in waitAndNotify after
// reconfiguring epFD.
eventFD int

// mu protects fdMap.
mu sync.Mutex

Expand All @@ -55,9 +59,20 @@ func newNotifier() (*notifier, error) {
return nil, err
}

eventFD, err := eventFDCreate()
if err != nil {
syscall.Close(epfd)
return nil, err
}

w := &notifier{
epFD: epfd,
fdMap: make(map[int32]*fdInfo),
epFD: epfd,
eventFD: eventFD,
fdMap: make(map[int32]*fdInfo),
}

if err := w.waitFD(int32(w.eventFD), &fdInfo{}, waiter.EventIn); err != nil {
return nil, err
}

go w.waitAndNotify() // S/R-SAFE: no waiter exists during save / load.
Expand Down Expand Up @@ -91,6 +106,11 @@ func (n *notifier) waitFD(fd int32, fi *fdInfo, mask waiter.EventMask) error {
}
}

// Restart epoll_wait in waitAndNotify.
if err := eventFDWrite(n.eventFD, 1); err != nil {
return err
}

return nil
}

Expand Down Expand Up @@ -156,6 +176,12 @@ func (n *notifier) waitAndNotify() error {

n.mu.Lock()
for i := 0; i < v; i++ {
if e[i].Fd == int32(n.eventFD) {
if _, err := eventFDRead(n.eventFD); err != nil {
return err
}
continue
}
if fi, ok := n.fdMap[e[i].Fd]; ok {
fi.queue.Notify(waiter.EventMaskFromLinux(e[i].Events))
}
Expand Down
25 changes: 25 additions & 0 deletions pkg/fdnotifier/poll_unsafe.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,28 @@ func epollWait(epfd int, events []syscall.EpollEvent, msec int) (int, error) {
}
return int(r), nil
}

func eventFDCreate() (int, error) {
eventFD, _, err := syscall.RawSyscall(syscall.SYS_EVENTFD2, 0, 0, 0)
if err != 0 {
return -1, err
}
return int(eventFD), nil
}

func eventFDWrite(eventFD int, v uint64) error {
if _, _, err := syscall.RawSyscall(syscall.SYS_WRITE, uintptr(eventFD), uintptr(unsafe.Pointer(&v)), 8); err != 0 {
return err
}

return nil
}

func eventFDRead(eventFD int) (uint64, error) {
var v uint64
if _, _, err := syscall.RawSyscall(syscall.SYS_READ, uintptr(eventFD), uintptr(unsafe.Pointer(&v)), 8); err != 0 {
return 0, err
}

return v, nil
}

0 comments on commit ec248da

Please sign in to comment.