Fix fdnotifier.AddFD() to handle the case when queue already has events.

`notifier.addFD()` was simply updating the FD map, assuming that the queue is
new and has no events registered.

However, this assumption may not hold for some callers of fdnotifier.AddFD(),
notably transport.connectionedEndpoint.SetBoundSocketFD(). This situation can
arise if the application does socket(2) -> epoll_ctl(EPOLL_CTL_ADD) -> bind(2).
This change gets rid of the said assumption.

Fixes #9848

PiperOrigin-RevId: 595171718
This commit is contained in:
Ayush Ranjan
2024-01-02 11:44:45 -08:00
committed by gVisor bot
parent de71aae89a
commit 65783256ca
+10 -5
View File
@@ -96,7 +96,7 @@ func (n *notifier) waitFD(fd int32, fi *fdInfo, mask waiter.EventMask) error {
}
// addFD adds an FD to the list of FDs observed by n.
func (n *notifier) addFD(fd int32, queue *waiter.Queue) {
func (n *notifier) addFD(fd int32, queue *waiter.Queue) error {
n.mu.Lock()
defer n.mu.Unlock()
@@ -105,8 +105,14 @@ func (n *notifier) addFD(fd int32, queue *waiter.Queue) {
panic(fmt.Sprintf("File descriptor %v added twice", fd))
}
// We have nothing to wait for at the moment. Just add it to the map.
n.fdMap[fd] = &fdInfo{queue: queue}
info := &fdInfo{queue: queue}
// We might already have something in queue to wait for.
if err := n.waitFD(fd, info, queue.Events()); err != nil {
return err
}
// Add it to the map.
n.fdMap[fd] = info
return nil
}
// updateFD updates the set of events the fd needs to be notified on.
@@ -188,8 +194,7 @@ func AddFD(fd int32, queue *waiter.Queue) error {
return shared.initErr
}
shared.notifier.addFD(fd, queue)
return nil
return shared.notifier.addFD(fd, queue)
}
// UpdateFD updates the set of events the fd needs to be notified on.