Skip to content

Commit f58e7f1

Browse files
committed
channel: unbounded: synchronize receiver disconnect with initialization
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 <[email protected]>
1 parent 00dcea6 commit f58e7f1

File tree

1 file changed

+11
-0
lines changed
  • crossbeam-channel/src/flavors

1 file changed

+11
-0
lines changed

crossbeam-channel/src/flavors/list.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,17 @@ impl<T> Channel<T> {
585585
let mut head = self.head.index.load(Ordering::Acquire);
586586
let mut block = self.head.block.load(Ordering::Acquire);
587587

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

0 commit comments

Comments
 (0)