mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
epoll: notify waiters if ReadEvents adds events
ReadEvents is racy with concurrent notifications and it has a code path that can add events to the ready queue. In such cases, it has to notify waiters. Users of ReadEvents() registers for events and then call ReadEvents. They expect that if ReadEvents returns nothing, they will get a notification when there will be something to read. PiperOrigin-RevId: 438449859
This commit is contained in:
@@ -212,6 +212,7 @@ func (e *EventPoll) eventsAvailable() bool {
|
||||
return false
|
||||
}
|
||||
defer func() {
|
||||
notify := true
|
||||
e.listsMu.Lock()
|
||||
e.readyList.PushFrontList(&readyList)
|
||||
var next *pollEntry
|
||||
@@ -221,12 +222,16 @@ func (e *EventPoll) eventsAvailable() bool {
|
||||
// entry.NotifyEvent() was called while we were running.
|
||||
waitingList.Remove(entry)
|
||||
e.readyList.PushBack(entry)
|
||||
notify = true
|
||||
} else {
|
||||
entry.curList = &e.waitingList
|
||||
}
|
||||
}
|
||||
e.waitingList.PushBackList(&waitingList)
|
||||
e.listsMu.Unlock()
|
||||
if notify {
|
||||
e.Notify(waiter.ReadableEvents)
|
||||
}
|
||||
}()
|
||||
|
||||
for it := readyList.Front(); it != nil; {
|
||||
@@ -287,6 +292,7 @@ func (e *EventPoll) ReadEvents(max int) []linux.EpollEvent {
|
||||
return nil
|
||||
}
|
||||
defer func() {
|
||||
notify := false
|
||||
e.listsMu.Lock()
|
||||
e.readyList.PushFrontList(&readyList)
|
||||
var next *pollEntry
|
||||
@@ -296,6 +302,7 @@ func (e *EventPoll) ReadEvents(max int) []linux.EpollEvent {
|
||||
// entry.NotifyEvent() was called while we were running.
|
||||
waitingList.Remove(entry)
|
||||
e.readyList.PushBack(entry)
|
||||
notify = true
|
||||
} else {
|
||||
entry.curList = &e.waitingList
|
||||
}
|
||||
@@ -307,6 +314,9 @@ func (e *EventPoll) ReadEvents(max int) []linux.EpollEvent {
|
||||
}
|
||||
e.disabledList.PushBackList(&disabledList)
|
||||
e.listsMu.Unlock()
|
||||
if notify {
|
||||
e.Notify(waiter.ReadableEvents)
|
||||
}
|
||||
}()
|
||||
|
||||
// Go through all entries we believe may be ready.
|
||||
|
||||
@@ -170,6 +170,7 @@ func (ep *EpollInstance) Readiness(mask waiter.EventMask) waiter.EventMask {
|
||||
return 0
|
||||
}
|
||||
defer func() {
|
||||
notify := false
|
||||
ep.readyMu.Lock()
|
||||
ep.ready.PushFrontList(&ready)
|
||||
var next *epollInterest
|
||||
@@ -179,11 +180,15 @@ func (ep *EpollInstance) Readiness(mask waiter.EventMask) waiter.EventMask {
|
||||
// epi.NotifyEvent() was called while we were running.
|
||||
notReady.Remove(epi)
|
||||
ep.ready.PushBack(epi)
|
||||
notify = true
|
||||
} else {
|
||||
epi.ready = false
|
||||
}
|
||||
}
|
||||
ep.readyMu.Unlock()
|
||||
if notify {
|
||||
ep.q.Notify(waiter.ReadableEvents)
|
||||
}
|
||||
}()
|
||||
|
||||
var next *epollInterest
|
||||
@@ -428,6 +433,7 @@ func (ep *EpollInstance) ReadEvents(events []linux.EpollEvent, maxEvents int) []
|
||||
return nil
|
||||
}
|
||||
defer func() {
|
||||
notify := false
|
||||
ep.readyMu.Lock()
|
||||
// epollInterests that we never checked are re-inserted at the start of
|
||||
// ep.ready. epollInterests that were ready are re-inserted at the end
|
||||
@@ -440,12 +446,16 @@ func (ep *EpollInstance) ReadEvents(events []linux.EpollEvent, maxEvents int) []
|
||||
// epi.NotifyEvent() was called while we were running.
|
||||
notReady.Remove(epi)
|
||||
ep.ready.PushBack(epi)
|
||||
notify = true
|
||||
} else {
|
||||
epi.ready = false
|
||||
}
|
||||
}
|
||||
ep.ready.PushBackList(&requeue)
|
||||
ep.readyMu.Unlock()
|
||||
if notify {
|
||||
ep.q.Notify(waiter.ReadableEvents)
|
||||
}
|
||||
}()
|
||||
|
||||
i := 0
|
||||
|
||||
Reference in New Issue
Block a user