Skip to content

Linux version of nonblocking TcpListener::accept differs from other platforms #67027

Open
@hashmap

Description

@hashmap

If TcpListener is in non-blocking mode then accepted streams inherit this property on all platforms except Linux, where accept4 is used instead of accept.

This code (with commented out stream.set_nonblocking(false)) unexpectedly works as expected on Linux only, because stream is in blocking mode.

 let listener = TcpListener::bind("0.0.0.0:3333").unwrap();
    listener.set_nonblocking(true).expect("set nonblocking");

    println!("Server listening on port 3333");
    loop {
        match listener.accept() {
            Ok((mut stream, _)) => {
                println!("New connection");
                //stream.set_nonblocking(false).expect("nonblock");
                stream
                    .set_read_timeout(Some(Duration::from_secs(10)))
                    .expect("set timeout");
                let mut data = [0 as u8; 2];
                match stream.read_exact(&mut data) {
                    Ok(_) => println!("Got message!"),
                    Err(e) => println!("Failed to receive data: {:?}", e),
                }
            }
            Err(_e) => {
                println!("Error: {:?}", e);
            }
        }
    }

accept4 man page explains:

On Linux, the new socket returned by accept() does not inherit file status
flags such as O_NONBLOCK and O_ASYNC from the listening socket. 
This behavior differs from the canonical BSD sockets implementation.
Portable programs should not rely on inheritance or noninheritance
of file status flags and always explicitly set all required flags on the socket
returned from accept(). 

I agree that code above should also set non_blocking explicitly, at the same time it would be nice to behave the same way on all platoftms.

Meta

rustc --version --verbose
rustc 1.37.0 (eae3437 2019-08-13)
binary: rustc
commit-hash: eae3437
commit-date: 2019-08-13
host: x86_64-unknown-linux-gnu
release: 1.37.0
LLVM version: 8.0

(but it applies to multiple versions)

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.O-linuxOperating system: LinuxT-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions