Skip to content

Commit c2d1ccb

Browse files
authored
bugfix: Remove listener if one already exists
This commit makes it so EventListener::listen() does not overwrite existing listeners if they already exist. If the listener is already registered in an event listener list, it removes the listener from that list before registering the new listener. This soundness bug was missed during #94. This is a patch-compatible fix for #100. We may also want an API-level fix for #100 as well. This is up for further discussion. Signed-off-by: John Nunley <[email protected]>
1 parent cc33cc5 commit c2d1ccb

File tree

2 files changed

+25
-1
lines changed

2 files changed

+25
-1
lines changed

src/lib.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -810,13 +810,24 @@ impl<T> EventListener<T> {
810810
///
811811
/// This method can only be called after the listener has been pinned, and must be called before
812812
/// the listener is polled.
813+
///
814+
/// Notifications that exist when this function is called will be discarded.
813815
pub fn listen(mut self: Pin<&mut Self>, event: &Event<T>) {
814816
let inner = {
815817
let inner = event.inner();
816818
unsafe { Arc::clone(&ManuallyDrop::new(Arc::from_raw(inner))) }
817819
};
818820

819-
let ListenerProject { event, listener } = self.as_mut().project().listener.project();
821+
let ListenerProject {
822+
event,
823+
mut listener,
824+
} = self.as_mut().project().listener.project();
825+
826+
// If an event is already registered, make sure to remove it.
827+
if let Some(current_event) = event.as_ref() {
828+
current_event.remove(listener.as_mut(), false);
829+
}
830+
820831
let inner = event.insert(inner);
821832
inner.insert(listener);
822833

tests/notify.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,3 +189,16 @@ fn notify_all_fair() {
189189
.poll(&mut Context::from_waker(&waker3))
190190
.is_ready());
191191
}
192+
193+
#[test]
194+
fn more_than_one_event() {
195+
let event = Event::new();
196+
let event2 = Event::new();
197+
198+
let mut listener = Box::pin(EventListener::<()>::new());
199+
listener.as_mut().listen(&event);
200+
listener.as_mut().listen(&event2);
201+
202+
drop(listener);
203+
event.notify(1);
204+
}

0 commit comments

Comments
 (0)