runtime: fix leaking registration entries when os registration fails (#6329)

This commit is contained in:
M.Amin Rayej 2024-02-15 03:13:08 +03:30 committed by GitHub
parent 2ce1cee0f9
commit b32826bc93
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 21 additions and 4 deletions

View File

@ -220,8 +220,17 @@ impl Handle {
let scheduled_io = self.registrations.allocate(&mut self.synced.lock())?;
let token = scheduled_io.token();
// TODO: if this returns an err, the `ScheduledIo` leaks...
self.registry.register(source, token, interest.to_mio())?;
// we should remove the `scheduled_io` from the `registrations` set if registering
// the `source` with the OS fails. Otherwise it will leak the `scheduled_io`.
if let Err(e) = self.registry.register(source, token, interest.to_mio()) {
// safety: `scheduled_io` is part of the `registrations` set.
unsafe {
self.registrations
.remove(&mut self.synced.lock(), &scheduled_io)
};
return Err(e);
}
// TODO: move this logic to `RegistrationSet` and use a `CountedLinkedList`
self.metrics.incr_fd_count();

View File

@ -102,13 +102,21 @@ impl RegistrationSet {
}
pub(super) fn release(&self, synced: &mut Synced) {
for io in synced.pending_release.drain(..) {
let pending = std::mem::take(&mut synced.pending_release);
for io in pending {
// safety: the registration is part of our list
let _ = unsafe { synced.registrations.remove(io.as_ref().into()) };
unsafe { self.remove(synced, io.as_ref()) }
}
self.num_pending_release.store(0, Release);
}
// This function is marked as unsafe, because the caller must make sure that
// `io` is part of the registration set.
pub(super) unsafe fn remove(&self, synced: &mut Synced, io: &ScheduledIo) {
let _ = synced.registrations.remove(io.into());
}
}
// Safety: `Arc` pins the inner data