Skip to content

Commit cd4c778

Browse files
committed
---
yaml --- r: 151110 b: refs/heads/try2 c: 7c5d48a h: refs/heads/master v: v3
1 parent 27dd543 commit cd4c778

File tree

17 files changed

+581
-721
lines changed

17 files changed

+581
-721
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ refs/heads/snap-stage3: 78a7676898d9f80ab540c6df5d4c9ce35bb50463
55
refs/heads/try: 519addf6277dbafccbb4159db4b710c37eaa2ec5
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
8-
refs/heads/try2: 66486518d5e1e4f0850024386b66a7aa790fc32f
8+
refs/heads/try2: 7c5d48a09e3648adc3d4f4118808a903758a9dda
99
refs/heads/dist-snap: ba4081a5a8573875fed17545846f6f6902c8ba8d
1010
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1111
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try2/src/liblibc/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ pub use funcs::bsd43::{shutdown};
225225
#[cfg(windows)] pub use consts::os::extra::{PIPE_UNLIMITED_INSTANCES, ERROR_ACCESS_DENIED};
226226
#[cfg(windows)] pub use consts::os::extra::{FILE_WRITE_ATTRIBUTES, FILE_READ_ATTRIBUTES};
227227
#[cfg(windows)] pub use consts::os::extra::{ERROR_PIPE_BUSY, ERROR_IO_PENDING};
228-
#[cfg(windows)] pub use consts::os::extra::{ERROR_PIPE_CONNECTED, WAIT_OBJECT_0};
228+
#[cfg(windows)] pub use consts::os::extra::{ERROR_PIPE_CONNECTED};
229229
#[cfg(windows)] pub use types::os::common::bsd44::{SOCKET};
230230
#[cfg(windows)] pub use types::os::common::posix01::{stat, utimbuf};
231231
#[cfg(windows)] pub use types::os::arch::extra::{HANDLE, BOOL, LPSECURITY_ATTRIBUTES};

branches/try2/src/libnative/io/c_win32.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,4 @@ extern "system" {
5959
optname: libc::c_int,
6060
optval: *mut libc::c_char,
6161
optlen: *mut libc::c_int) -> libc::c_int;
62-
63-
pub fn CancelIo(hFile: libc::HANDLE) -> libc::BOOL;
6462
}

branches/try2/src/libnative/io/mod.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ pub use self::process::Process;
4444
pub mod addrinfo;
4545
pub mod net;
4646
pub mod process;
47-
mod util;
4847

4948
#[cfg(unix)]
5049
#[path = "file_unix.rs"]
@@ -178,9 +177,8 @@ impl rtio::IoFactory for IoFactory {
178177
fn unix_bind(&mut self, path: &CString) -> IoResult<~RtioUnixListener:Send> {
179178
pipe::UnixListener::bind(path).map(|s| ~s as ~RtioUnixListener:Send)
180179
}
181-
fn unix_connect(&mut self, path: &CString,
182-
timeout: Option<u64>) -> IoResult<~RtioPipe:Send> {
183-
pipe::UnixStream::connect(path, timeout).map(|s| ~s as ~RtioPipe:Send)
180+
fn unix_connect(&mut self, path: &CString) -> IoResult<~RtioPipe:Send> {
181+
pipe::UnixStream::connect(path).map(|s| ~s as ~RtioPipe:Send)
184182
}
185183
fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>,
186184
hint: Option<ai::Hint>) -> IoResult<~[ai::Info]> {

branches/try2/src/libnative/io/net.rs

Lines changed: 122 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,13 @@ use std::cast;
1313
use std::io::net::ip;
1414
use std::io;
1515
use std::mem;
16+
use std::os;
17+
use std::ptr;
1618
use std::rt::rtio;
1719
use std::sync::arc::UnsafeArc;
1820

1921
use super::{IoResult, retry, keep_going};
2022
use super::c;
21-
use super::util;
2223

2324
////////////////////////////////////////////////////////////////////////////////
2425
// sockaddr and misc bindings
@@ -117,8 +118,8 @@ fn setsockopt<T>(fd: sock_t, opt: libc::c_int, val: libc::c_int,
117118
}
118119
}
119120

120-
pub fn getsockopt<T: Copy>(fd: sock_t, opt: libc::c_int,
121-
val: libc::c_int) -> IoResult<T> {
121+
fn getsockopt<T: Copy>(fd: sock_t, opt: libc::c_int,
122+
val: libc::c_int) -> IoResult<T> {
122123
unsafe {
123124
let mut slot: T = mem::init();
124125
let mut len = mem::size_of::<T>() as libc::socklen_t;
@@ -144,6 +145,21 @@ fn last_error() -> io::IoError {
144145
super::last_error()
145146
}
146147

148+
fn ms_to_timeval(ms: u64) -> libc::timeval {
149+
libc::timeval {
150+
tv_sec: (ms / 1000) as libc::time_t,
151+
tv_usec: ((ms % 1000) * 1000) as libc::suseconds_t,
152+
}
153+
}
154+
155+
fn timeout(desc: &'static str) -> io::IoError {
156+
io::IoError {
157+
kind: io::TimedOut,
158+
desc: desc,
159+
detail: None,
160+
}
161+
}
162+
147163
#[cfg(windows)] unsafe fn close(sock: sock_t) { let _ = libc::closesocket(sock); }
148164
#[cfg(unix)] unsafe fn close(sock: sock_t) { let _ = libc::close(sock); }
149165

@@ -254,7 +270,7 @@ impl TcpStream {
254270
let addrp = &addr as *_ as *libc::sockaddr;
255271
match timeout {
256272
Some(timeout) => {
257-
try!(util::connect_timeout(fd, addrp, len, timeout));
273+
try!(TcpStream::connect_timeout(fd, addrp, len, timeout));
258274
Ok(ret)
259275
},
260276
None => {
@@ -266,6 +282,84 @@ impl TcpStream {
266282
}
267283
}
268284

285+
// See http://developerweb.net/viewtopic.php?id=3196 for where this is
286+
// derived from.
287+
fn connect_timeout(fd: sock_t,
288+
addrp: *libc::sockaddr,
289+
len: libc::socklen_t,
290+
timeout_ms: u64) -> IoResult<()> {
291+
#[cfg(unix)] use INPROGRESS = libc::EINPROGRESS;
292+
#[cfg(windows)] use INPROGRESS = libc::WSAEINPROGRESS;
293+
#[cfg(unix)] use WOULDBLOCK = libc::EWOULDBLOCK;
294+
#[cfg(windows)] use WOULDBLOCK = libc::WSAEWOULDBLOCK;
295+
296+
// Make sure the call to connect() doesn't block
297+
try!(set_nonblocking(fd, true));
298+
299+
let ret = match unsafe { libc::connect(fd, addrp, len) } {
300+
// If the connection is in progress, then we need to wait for it to
301+
// finish (with a timeout). The current strategy for doing this is
302+
// to use select() with a timeout.
303+
-1 if os::errno() as int == INPROGRESS as int ||
304+
os::errno() as int == WOULDBLOCK as int => {
305+
let mut set: c::fd_set = unsafe { mem::init() };
306+
c::fd_set(&mut set, fd);
307+
match await(fd, &mut set, timeout_ms) {
308+
0 => Err(timeout("connection timed out")),
309+
-1 => Err(last_error()),
310+
_ => {
311+
let err: libc::c_int = try!(
312+
getsockopt(fd, libc::SOL_SOCKET, libc::SO_ERROR));
313+
if err == 0 {
314+
Ok(())
315+
} else {
316+
Err(io::IoError::from_errno(err as uint, true))
317+
}
318+
}
319+
}
320+
}
321+
322+
-1 => Err(last_error()),
323+
_ => Ok(()),
324+
};
325+
326+
// be sure to turn blocking I/O back on
327+
try!(set_nonblocking(fd, false));
328+
return ret;
329+
330+
#[cfg(unix)]
331+
fn set_nonblocking(fd: sock_t, nb: bool) -> IoResult<()> {
332+
let set = nb as libc::c_int;
333+
super::mkerr_libc(retry(|| unsafe { c::ioctl(fd, c::FIONBIO, &set) }))
334+
}
335+
#[cfg(windows)]
336+
fn set_nonblocking(fd: sock_t, nb: bool) -> IoResult<()> {
337+
let mut set = nb as libc::c_ulong;
338+
if unsafe { c::ioctlsocket(fd, c::FIONBIO, &mut set) != 0 } {
339+
Err(last_error())
340+
} else {
341+
Ok(())
342+
}
343+
}
344+
345+
#[cfg(unix)]
346+
fn await(fd: sock_t, set: &mut c::fd_set, timeout: u64) -> libc::c_int {
347+
let start = ::io::timer::now();
348+
retry(|| unsafe {
349+
// Recalculate the timeout each iteration (it is generally
350+
// undefined what the value of the 'tv' is after select
351+
// returns EINTR).
352+
let tv = ms_to_timeval(timeout - (::io::timer::now() - start));
353+
c::select(fd + 1, ptr::null(), &*set, ptr::null(), &tv)
354+
})
355+
}
356+
#[cfg(windows)]
357+
fn await(_fd: sock_t, set: &mut c::fd_set, timeout: u64) -> libc::c_int {
358+
let tv = ms_to_timeval(timeout);
359+
unsafe { c::select(1, ptr::null(), &*set, ptr::null(), &tv) }
360+
}
361+
}
362+
269363
pub fn fd(&self) -> sock_t {
270364
// This unsafety is fine because it's just a read-only arc
271365
unsafe { (*self.inner.get()).fd }
@@ -439,7 +533,7 @@ impl TcpAcceptor {
439533

440534
pub fn native_accept(&mut self) -> IoResult<TcpStream> {
441535
if self.deadline != 0 {
442-
try!(util::accept_deadline(self.fd(), self.deadline));
536+
try!(self.accept_deadline());
443537
}
444538
unsafe {
445539
let mut storage: libc::sockaddr_storage = mem::init();
@@ -456,6 +550,25 @@ impl TcpAcceptor {
456550
}
457551
}
458552
}
553+
554+
fn accept_deadline(&mut self) -> IoResult<()> {
555+
let mut set: c::fd_set = unsafe { mem::init() };
556+
c::fd_set(&mut set, self.fd());
557+
558+
match retry(|| {
559+
// If we're past the deadline, then pass a 0 timeout to select() so
560+
// we can poll the status of the socket.
561+
let now = ::io::timer::now();
562+
let ms = if self.deadline > now {0} else {self.deadline - now};
563+
let tv = ms_to_timeval(ms);
564+
let n = if cfg!(windows) {1} else {self.fd() as libc::c_int + 1};
565+
unsafe { c::select(n, &set, ptr::null(), ptr::null(), &tv) }
566+
}) {
567+
-1 => Err(last_error()),
568+
0 => Err(timeout("accept timed out")),
569+
_ => return Ok(()),
570+
}
571+
}
459572
}
460573

461574
impl rtio::RtioSocket for TcpAcceptor {
@@ -472,7 +585,10 @@ impl rtio::RtioTcpAcceptor for TcpAcceptor {
472585
fn accept_simultaneously(&mut self) -> IoResult<()> { Ok(()) }
473586
fn dont_accept_simultaneously(&mut self) -> IoResult<()> { Ok(()) }
474587
fn set_timeout(&mut self, timeout: Option<u64>) {
475-
self.deadline = timeout.map(|a| ::io::timer::now() + a).unwrap_or(0);
588+
self.deadline = match timeout {
589+
None => 0,
590+
Some(t) => ::io::timer::now() + t,
591+
};
476592
}
477593
}
478594

0 commit comments

Comments
 (0)