From 65783256ca99c40e393182f8bae8aeb22a79997b Mon Sep 17 00:00:00 2001 From: Ayush Ranjan Date: Tue, 2 Jan 2024 11:42:09 -0800 Subject: [PATCH] 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 --- pkg/fdnotifier/fdnotifier.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/pkg/fdnotifier/fdnotifier.go b/pkg/fdnotifier/fdnotifier.go index 0858e0866..dc3a2248e 100644 --- a/pkg/fdnotifier/fdnotifier.go +++ b/pkg/fdnotifier/fdnotifier.go @@ -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.