From e901c4caf30353f6adf12e6b10a46a4de517ec9d Mon Sep 17 00:00:00 2001 From: xales Date: Mon, 27 Jan 2014 09:24:01 -0500 Subject: [PATCH] Set SO_REUSEADDR by default in libnative. Fixes std::net test error when re-running too quickly. --- src/libnative/io/net.rs | 11 +++++++++++ src/libstd/io/net/tcp.rs | 40 ++++++++++++++++++++++++++++++++++++++++ src/libstd/libc.rs | 4 ++++ 3 files changed, 55 insertions(+) diff --git a/src/libnative/io/net.rs b/src/libnative/io/net.rs index 9be4247b056..2f4bec22755 100644 --- a/src/libnative/io/net.rs +++ b/src/libnative/io/net.rs @@ -348,6 +348,17 @@ impl TcpListener { let (addr, len) = addr_to_sockaddr(addr); let addrp = &addr as *libc::sockaddr_storage; let ret = TcpListener { fd: fd }; + // On platforms with Berkeley-derived sockets, this allows + // to quickly rebind a socket, without needing to wait for + // the OS to clean up the previous one. + if cfg!(unix) { + match setsockopt(fd, libc::SOL_SOCKET, + libc::SO_REUSEADDR, + 1 as libc::c_int) { + Err(n) => { return Err(n); }, + Ok(..) => { } + } + } match libc::bind(fd, addrp as *libc::sockaddr, len as libc::socklen_t) { -1 => Err(super::last_error()), diff --git a/src/libstd/io/net/tcp.rs b/src/libstd/io/net/tcp.rs index 9f0bf84c8d8..92efc4e9306 100644 --- a/src/libstd/io/net/tcp.rs +++ b/src/libstd/io/net/tcp.rs @@ -609,4 +609,44 @@ mod test { c.write([1]); p.recv(); }) + + iotest!(fn double_bind() { + let mut called = false; + io_error::cond.trap(|e| { + assert!(e.kind == ConnectionRefused || e.kind == OtherIoError); + called = true; + }).inside(|| { + let addr = next_test_ip4(); + let listener = TcpListener::bind(addr).unwrap().listen(); + assert!(listener.is_some()); + let listener2 = TcpListener::bind(addr).and_then(|l| + l.listen()); + assert!(listener2.is_none()); + }); + assert!(called); + }) + + iotest!(fn fast_rebind() { + let addr = next_test_ip4(); + let (port, chan) = Chan::new(); + + do spawn { + port.recv(); + let stream = TcpStream::connect(addr); + // Close + port.recv(); + } + + { + let mut acceptor = TcpListener::bind(addr).listen(); + chan.send(()); + { + let stream = acceptor.accept(); + // Close client + chan.send(()); + } + // Close listener + } + let listener = TcpListener::bind(addr); + }) } diff --git a/src/libstd/libc.rs b/src/libstd/libc.rs index d5f185880fa..dccadf2e00b 100644 --- a/src/libstd/libc.rs +++ b/src/libstd/libc.rs @@ -1547,6 +1547,7 @@ pub mod consts { pub static SOL_SOCKET: c_int = 0xffff; pub static SO_KEEPALIVE: c_int = 8; pub static SO_BROADCAST: c_int = 32; + pub static SO_REUSEADDR: c_int = 4; } pub mod extra { use libc::types::os::arch::c95::c_int; @@ -2266,6 +2267,7 @@ pub mod consts { pub static SOL_SOCKET: c_int = 1; pub static SO_KEEPALIVE: c_int = 9; pub static SO_BROADCAST: c_int = 6; + pub static SO_REUSEADDR: c_int = 2; } #[cfg(target_arch = "x86")] #[cfg(target_arch = "x86_64")] @@ -2707,6 +2709,7 @@ pub mod consts { pub static SOL_SOCKET: c_int = 0xffff; pub static SO_KEEPALIVE: c_int = 0x0008; pub static SO_BROADCAST: c_int = 0x0020; + pub static SO_REUSEADDR: c_int = 0x0004; } pub mod extra { use libc::types::os::arch::c95::c_int; @@ -3083,6 +3086,7 @@ pub mod consts { pub static SOL_SOCKET: c_int = 0xffff; pub static SO_KEEPALIVE: c_int = 0x0008; pub static SO_BROADCAST: c_int = 0x0020; + pub static SO_REUSEADDR: c_int = 0x0004; } pub mod extra { use libc::types::os::arch::c95::c_int;