Skip to content

MeasureManyStream never terminates (returns None) #3

@ThinkerDreamer

Description

@ThinkerDreamer

Description

MeasureManyStream never returns None to signal stream completion. After all ping requests have been sent and all responses received, poll_next_unpin returns Poll::Pending forever instead of Poll::Ready(None).

This causes while let loops to hang indefinitely:

let mut stream = pinger.measure_many([localhost].into_iter());

// This hangs forever after receiving the ping response
while let Some((addr, rtt)) = stream.next().await {
    println!("{addr}: {rtt:?}");
}
// Never reaches here

Root Cause

In pinger.rs, poll_next_unpin has return type Poll<(V, Duration)> (no Option!) and always returns Poll::Pending at the end:

pub fn poll_next_unpin(&mut self, cx: &mut Context<'_>) -> Poll<(V, Duration)> {
    // ... process results ...
    Poll::Pending  // Always pending, never signals completion
}

The Stream implementation then wraps everything in Some, so it can never return None:

fn poll_next(...) -> Poll<Option<Self::Item>> {
    let result = ready!(self.poll_next_unpin(cx));
    Poll::Ready(Some(result))  // Always Some!
}

Expected Behavior

The stream should return None when:

  1. All addresses in send_queue have been sent
  2. All entries in in_flight have received responses (or timed out)

Suggested Fix

  1. Change poll_next_unpin return type to Poll<Option<(V, Duration)>>
  2. Add completion check: if send_queue.peek().is_none() && in_flight.is_empty() { return Poll::Ready(None); }
  3. Update Stream impl to pass through the Option directly
  4. Same changes needed for DualstackMeasureManyStream

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions