libpnet / libpnet/libpnet

next_with_timeout() with zero timeout waits indefinitely

Open
#671 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
2.6k
Forks
329
PR merge metrics
No merged PRs in 30d

Description

The following code is expected to poll in a tight loop, instead it waits indefinitely for every packet (confirmed with strace(1)):

use pnet::{transport::*, packet::ip::*};
use std::time::Duration;

fn main() {
    let (_, mut tx) = transport_channel(
        4096, TransportChannelType::Layer4(
            TransportProtocol::Ipv4(
                IpNextHeaderProtocols::Icmp
    ))).unwrap();
    loop {
        let _ = icmp_packet_iter(&mut tx).next_with_timeout(Duration::new(0, 0));
    }
}

I suspect this is because socket option SO_RCVTIMEO interprets zero timeout as infinite. From socket(7) man:

If the timeout is set to zero (the default) then the operation will never timeout.

The problem can be solved by specifying timeout as the smallest non-zero value (1000ns since timeval.tv_usec is in microseconds):

use pnet::{transport::*, packet::ip::*};
use std::time::Duration;

fn main() {
    let (_, mut tx) = transport_channel(
        4096, TransportChannelType::Layer4(
            TransportProtocol::Ipv4(
                IpNextHeaderProtocols::Icmp
    ))).unwrap();
    loop {
        let _ = icmp_packet_iter(&mut tx).next_with_timeout(Duration::new(0, 1000));
    }
}

Either values from 0 to 999ns should be automatically converted to 1us or the documentation should be updated to mention this unexpected behavior. Since there is already a blocking method next() I prefer the former.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by locating the Rust implementation of next_with_timeout() and how Duration is converted into SO_RCVTIMEO, then reproduce the zero-timeout behavior with the example in the issue. Add or update tests for zero and sub-microsecond durations; done means these calls return without waiting indefinitely while the existing blocking behavior remains unchanged.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
networking
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.