Skip to content

Commit

Permalink
Merge branch 'fix-unparking-receiver-drop'
Browse files Browse the repository at this point in the history
  • Loading branch information
faern committed Feb 22, 2025
2 parents 208cf17 + 66d7a23 commit 9bbdd69
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 25 deletions.
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.


## [Unreleased]

- Handle the UNPARKING state correctly in `Receiver::drop()`.
### Fixed
- Handle the `UNPARKING` state correctly in `Receiver::drop()`. Fixes a panic that could
occur if a `Receiver` had been first polled as a future and then was being dropped
in parallel with the `Sender` sending a message.


## [0.1.10] - 2025-02-04
Expand Down
44 changes: 21 additions & 23 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,9 @@ use loom::{
sync::atomic::{fence, AtomicU8, Ordering::*},
};

#[cfg(all(feature = "async", not(oneshot_loom)))]
#[cfg(all(any(feature = "std", feature = "async"), not(oneshot_loom)))]
use core::hint;
#[cfg(all(feature = "async", oneshot_loom))]
#[cfg(all(any(feature = "std", feature = "async"), oneshot_loom))]
use loom::hint;

#[cfg(feature = "async")]
Expand Down Expand Up @@ -1067,31 +1067,29 @@ impl<T> Drop for Receiver<T> {
// SAFETY: see safety comment at top of function
unsafe { dealloc(self.channel_ptr) };
}
// The sender has observed the RECEIVING state and is currently reading the waker from
// a poll. We need to loop here until we observe the MESSAGE or DISCONNECTED state.
// This receiver was previously polled, so the channel was in the RECEIVING state.
// But the sender has observed the RECEIVING state and is currently reading the waker
// to wake us up. We need to loop here until we observe the MESSAGE or DISCONNECTED state.
// We busy loop here since we know the sender is done very soon.
#[cfg(any(feature = "std", feature = "async"))]
UNPARKING => loop {
hint::spin_loop();
// ORDERING: The load above has already synchronized with the write of the message.
match channel.state.load(Relaxed) {
MESSAGE => {
// SAFETY: we are in the message state so the message is initialized
unsafe { channel.drop_message() };

// SAFETY: see safety comment at top of function
unsafe { dealloc(self.channel_ptr) };
break;
}
DISCONNECTED => {
// SAFETY: see safety comment at top of function
unsafe { dealloc(self.channel_ptr) };
break;
UNPARKING => {
loop {
hint::spin_loop();
// ORDERING: The swap above has already synchronized with the write of the message.
match channel.state.load(Relaxed) {
MESSAGE => {
// SAFETY: we are in the message state so the message is initialized
unsafe { channel.drop_message() };
break;
}
DISCONNECTED => break,
UNPARKING => (),
_ => unreachable!(),
}
UNPARKING => (),
_ => unreachable!(),
}
},
// SAFETY: see safety comment at top of function
unsafe { dealloc(self.channel_ptr) };
}
_ => unreachable!(),
}
}
Expand Down

0 comments on commit 9bbdd69

Please sign in to comment.