Skip to content

Commit c6bd053

Browse files
committed
auto merge of #11845 : xales/rust/libnative, r=alexcrichton
Fixes std::net test error when re-running too quickly. Suggested by @cmr
2 parents b3d10f4 + e901c4c commit c6bd053

File tree

3 files changed

+55
-0
lines changed

3 files changed

+55
-0
lines changed

src/libnative/io/net.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,17 @@ impl TcpListener {
348348
let (addr, len) = addr_to_sockaddr(addr);
349349
let addrp = &addr as *libc::sockaddr_storage;
350350
let ret = TcpListener { fd: fd };
351+
// On platforms with Berkeley-derived sockets, this allows
352+
// to quickly rebind a socket, without needing to wait for
353+
// the OS to clean up the previous one.
354+
if cfg!(unix) {
355+
match setsockopt(fd, libc::SOL_SOCKET,
356+
libc::SO_REUSEADDR,
357+
1 as libc::c_int) {
358+
Err(n) => { return Err(n); },
359+
Ok(..) => { }
360+
}
361+
}
351362
match libc::bind(fd, addrp as *libc::sockaddr,
352363
len as libc::socklen_t) {
353364
-1 => Err(super::last_error()),

src/libstd/io/net/tcp.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,4 +609,44 @@ mod test {
609609
c.write([1]);
610610
p.recv();
611611
})
612+
613+
iotest!(fn double_bind() {
614+
let mut called = false;
615+
io_error::cond.trap(|e| {
616+
assert!(e.kind == ConnectionRefused || e.kind == OtherIoError);
617+
called = true;
618+
}).inside(|| {
619+
let addr = next_test_ip4();
620+
let listener = TcpListener::bind(addr).unwrap().listen();
621+
assert!(listener.is_some());
622+
let listener2 = TcpListener::bind(addr).and_then(|l|
623+
l.listen());
624+
assert!(listener2.is_none());
625+
});
626+
assert!(called);
627+
})
628+
629+
iotest!(fn fast_rebind() {
630+
let addr = next_test_ip4();
631+
let (port, chan) = Chan::new();
632+
633+
do spawn {
634+
port.recv();
635+
let stream = TcpStream::connect(addr);
636+
// Close
637+
port.recv();
638+
}
639+
640+
{
641+
let mut acceptor = TcpListener::bind(addr).listen();
642+
chan.send(());
643+
{
644+
let stream = acceptor.accept();
645+
// Close client
646+
chan.send(());
647+
}
648+
// Close listener
649+
}
650+
let listener = TcpListener::bind(addr);
651+
})
612652
}

src/libstd/libc.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1547,6 +1547,7 @@ pub mod consts {
15471547
pub static SOL_SOCKET: c_int = 0xffff;
15481548
pub static SO_KEEPALIVE: c_int = 8;
15491549
pub static SO_BROADCAST: c_int = 32;
1550+
pub static SO_REUSEADDR: c_int = 4;
15501551
}
15511552
pub mod extra {
15521553
use libc::types::os::arch::c95::c_int;
@@ -2266,6 +2267,7 @@ pub mod consts {
22662267
pub static SOL_SOCKET: c_int = 1;
22672268
pub static SO_KEEPALIVE: c_int = 9;
22682269
pub static SO_BROADCAST: c_int = 6;
2270+
pub static SO_REUSEADDR: c_int = 2;
22692271
}
22702272
#[cfg(target_arch = "x86")]
22712273
#[cfg(target_arch = "x86_64")]
@@ -2707,6 +2709,7 @@ pub mod consts {
27072709
pub static SOL_SOCKET: c_int = 0xffff;
27082710
pub static SO_KEEPALIVE: c_int = 0x0008;
27092711
pub static SO_BROADCAST: c_int = 0x0020;
2712+
pub static SO_REUSEADDR: c_int = 0x0004;
27102713
}
27112714
pub mod extra {
27122715
use libc::types::os::arch::c95::c_int;
@@ -3083,6 +3086,7 @@ pub mod consts {
30833086
pub static SOL_SOCKET: c_int = 0xffff;
30843087
pub static SO_KEEPALIVE: c_int = 0x0008;
30853088
pub static SO_BROADCAST: c_int = 0x0020;
3089+
pub static SO_REUSEADDR: c_int = 0x0004;
30863090
}
30873091
pub mod extra {
30883092
use libc::types::os::arch::c95::c_int;

0 commit comments

Comments
 (0)