rust-lang / socket2

Advanced configuration options for sockets.
https://docs.rs/socket2
Apache License 2.0
683 stars 227 forks source link

Error: BoxSend(Os { code: 98, kind: AddrInUse, message: "Address already in use" }) #489

Closed kolbma closed 9 months ago

kolbma commented 9 months ago

Hello,

could it be that you miss some kind of free/close the socket-binding, so that we have to wait for Linux to cleanup after some timeout?

If I use socket2 the 1st time it works and after process exit and checking there is no process and no listener at the tcp port anylonger, nevertheless in the next run I get
Error: BoxSend(Os { code: 98, kind: AddrInUse, message: "Address already in use" })

Looks like I have to wait 60 seconds each time between stopping and restarting my daemon process when using socket2 sockets.
Are you checking available TIME-WAIT states instead/in addition of LISTEN?
std::net doesn't have this problem.

My code looks like this and addresses is an array with a single address 127.0.0.1:9090.

                // let addresses: &Vec<SocketAddr>;
                let mut socket =
                    socket2::Socket::new(socket2::Domain::IPV4, socket2::Type::STREAM, None)?;
                socket.set_reuse_address(true)?;

                for address in addresses {
                    socket = socket2::Socket::new(
                        socket2::Domain::for_address(*address),
                        socket2::Type::STREAM,
                        None,
                    )?;

                    if let Err(e) = socket.bind(&(*address).into()) {
                        err = Some(e);
                        continue;
                    }
                    if let Err(e) = socket.listen(1024) {
                        err = Some(e);
                        continue;
                    }
                    err = None;
                    break;
                }

                if let Some(err) = err {
                    log::error!("socket bind fail: {err:?}");
                    return Err(err);
                }
Thomasdezeeuw commented 9 months ago

You need to call set_reuse_address on all sockets before binding on the address.

Please read the documentation on SO_REUSEPORT in the socket(7) manual.

kolbma commented 9 months ago

@Thomasdezeeuw Ooch, tomatoes..., don't know why I didn't see that set_reuse_address was for the wrong socket, had it before after binding, but like that it has been complete useless :-( Thanks, using a Result now, instead of dummy socket assign.