Skip to content

SO_REUSEADDR should be set on TCP sockets even when not binding to a specific port #12402

@wingo

Description

@wingo

When writing a test that sockets have SO_REUSEADDR set for wasip3, @saulecabrera ran into a bug that shows up only on Linux (not mac, not windows):

async fn test_reuseaddr(family: IpAddressFamily) {
    let client = TcpSocket::create(family).unwrap();
    let local_addr = {
        let server = TcpSocket::create(family).unwrap();
        let addr = IpSocketAddress::localhost(family, 0);
        server.bind(addr).unwrap();
        let local_addr = server.get_local_address().unwrap();
        let mut accept = server.listen().unwrap();
        join!(
            // Change the state to connected.
            async {
                client.connect(local_addr).await.unwrap();
            },
            async {
                let sock = accept.next().await.unwrap();
                let (mut send_tx, send_rx) = wit_stream::new();
                join!(
                    async {
                        sock.send(send_rx).await.unwrap();
                    },
                    async {
                        let remaining = send_tx.write_all(vec![0; 1]).await;
                        assert!(remaining.is_empty());
                        drop(send_tx);
                    }
                );
            }
        );
        local_addr
    };

    // Immediately try to connect to the same after the connection is
    // dropped.  According to the spec, `SO_REUSEADDR` should be set
    // by default, so the next connection should not be affected by
    // the `TIME_WAIT` state.
    let next = TcpSocket::create(family).unwrap();
    next.bind(local_addr).unwrap();
    next.listen().unwrap();
}

When next is bound to the same local_addr, the bind fails. It is apparently because the first socket server wasn't opened with REUSEADDR, because port is 0 : https://github.com/bytecodealliance/wasmtime/blob/main/crates/wasi/src/sockets/util.rs#L345. If I change the condition on that line to unconditional "true", Saúl's wasi test passes, and no wasmtime test fails.

So, I propose that wasmtime should just always set REUSEADDR (unless we are on a windows system).

Full test here: WebAssembly/wasi-testsuite#205

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugIncorrect behavior in the current implementation that needs fixingwasiIssues pertaining to WASI

    Type

    No type

    Projects

    Status

    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions