Skip to content

Commit

Permalink
channel: unbounded: synchronize receiver disconnect with initialization
Browse files Browse the repository at this point in the history
We must take into account the case where the channel has messages in the
block pointed to by `tail` but the head is still pointing to a null
pointer. This can happen with two concurrent senders if one gets
preempted during initialization.

Signed-off-by: Petros Angelatos <petrosagg@gmail.com>
  • Loading branch information
petrosagg authored and taiki-e committed Apr 9, 2023
1 parent 721382b commit ab1b313
Showing 1 changed file with 11 additions and 0 deletions.
11 changes: 11 additions & 0 deletions crossbeam-channel/src/flavors/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,17 @@ impl<T> Channel<T> {
let mut head = self.head.index.load(Ordering::Acquire);
let mut block = self.head.block.load(Ordering::Acquire);

// If we're going to be dropping messages we need to synchronize with initialization
if head >> SHIFT != tail >> SHIFT {
// The block can be null here only if a sender is in the process of initializing the
// channel while another sender managed to send a message by inserting it into the
// semi-initialized channel and advanced the tail.
// In that case, just wait until it gets initialized.
while block.is_null() {
backoff.snooze();
block = self.head.block.load(Ordering::Acquire);
}
}
unsafe {
// Drop all messages between head and tail and deallocate the heap-allocated blocks.
while head >> SHIFT != tail >> SHIFT {
Expand Down

0 comments on commit ab1b313

Please sign in to comment.