diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index 5023d69240893..4a411654e0f39 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -1818,4 +1818,31 @@ mod tests { let addr = listener.local_addr().unwrap(); TcpStream::connect_timeout(&addr, Duration::from_secs(2)).unwrap(); } + + #[test] + fn nonblocking_accept() { + let socket_addr = next_test_ip4(); + let listener = t!(TcpListener::bind(&socket_addr)); + t!(listener.set_nonblocking(true)); + + let _t = thread::spawn(move || { + t!(TcpStream::connect(&("localhost", socket_addr.port()))); + thread::sleep(Duration::from_millis(1000)); + }); + + loop { + match listener.accept() { + Ok((mut stream, _)) => { + let mut buf = [0; 2]; + match stream.read_exact(&mut buf) { + Ok(_) => panic!("expected error"), + Err(ref e) if e.kind() == ErrorKind::WouldBlock => return, + Err(e) => panic!("unexpected error {:?}", e), + } + } + Err(e) if e.kind() == ErrorKind::WouldBlock => {} + Err(e) => panic!("unexpected error {:?}", e), + } + } + } } diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index 79b0dc02978f3..a0e0687bc7a4c 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -189,7 +189,14 @@ impl Socket { flags: c_int ) -> c_int } - let res = cvt_r(|| unsafe { accept4(self.0.raw(), storage, len, libc::SOCK_CLOEXEC) }); + let is_blocking = + unsafe { (cvt(libc::fcntl(self.0.raw(), libc::F_GETFL))? & libc::O_NONBLOCK) != 0 }; + let accept_flags = if is_blocking { + libc::SOCK_CLOEXEC | libc::SOCK_NONBLOCK + } else { + libc::SOCK_CLOEXEC + }; + let res = cvt_r(|| unsafe { accept4(self.0.raw(), storage, len, accept_flags) }); match res { Ok(fd) => return Ok(Socket(FileDesc::new(fd))), Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {} @@ -329,7 +336,11 @@ impl Socket { pub fn take_error(&self) -> io::Result> { let raw: c_int = getsockopt(self, libc::SOL_SOCKET, libc::SO_ERROR)?; - if raw == 0 { Ok(None) } else { Ok(Some(io::Error::from_raw_os_error(raw as i32))) } + if raw == 0 { + Ok(None) + } else { + Ok(Some(io::Error::from_raw_os_error(raw as i32))) + } } }