libnative/io: generic retry() for Unix 64 bit read/write().

Win32/WinSock APIs never call WSASetLastError() with WSAEINTR
unless a programmer specifically cancels the ongoing blocking call by
a deprecated WinSock1 API WSACancelBlockingCall().
So the errno check was simply removed and retry() became an id function
on Windows.
Note: Windows' equivalent of SIGINT is always handled in a separate thread:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682541%28v=vs.85%29.aspx
"CTRL+C and CTRL+BREAK Signals"

Also, incidentally rename a type parameter and clean up some module imports.
This commit is contained in:
NODA, Kai 2014-09-05 15:05:22 +08:00
parent 67b97ab6d2
commit 52e99cbcaa
3 changed files with 22 additions and 34 deletions

View File

@ -11,12 +11,10 @@
//! Blocking posix-based file I/O
use alloc::arc::Arc;
use libc::{c_int, c_void};
use libc;
use libc::{mod, c_int, c_void};
use std::c_str::CString;
use std::mem;
use std::rt::rtio;
use std::rt::rtio::IoResult;
use std::rt::rtio::{mod, IoResult};
use io::{retry, keep_going};
use io::util;
@ -55,7 +53,7 @@ impl FileDesc {
let ret = retry(|| unsafe {
libc::read(self.fd(),
buf.as_mut_ptr() as *mut libc::c_void,
buf.len() as libc::size_t) as libc::c_int
buf.len() as libc::size_t)
});
if ret == 0 {
Err(util::eof())
@ -93,7 +91,7 @@ impl rtio::RtioFileStream for FileDesc {
match retry(|| unsafe {
libc::pread(self.fd(), buf.as_ptr() as *mut _,
buf.len() as libc::size_t,
offset as libc::off_t) as libc::c_int
offset as libc::off_t)
}) {
-1 => Err(super::last_error()),
n => Ok(n as int)
@ -103,7 +101,7 @@ impl rtio::RtioFileStream for FileDesc {
super::mkerr_libc(retry(|| unsafe {
libc::pwrite(self.fd(), buf.as_ptr() as *const _,
buf.len() as libc::size_t, offset as libc::off_t)
} as c_int))
}))
}
fn seek(&mut self, pos: i64, whence: rtio::SeekStyle) -> IoResult<u64> {
let whence = match whence {

View File

@ -23,12 +23,11 @@
#![allow(non_snake_case)]
use libc::c_int;
use libc;
use libc::{mod, c_int};
use std::c_str::CString;
use std::os;
use std::rt::rtio;
use std::rt::rtio::{IoResult, IoError};
use std::rt::rtio::{mod, IoResult, IoError};
use std::num;
// Local re-exports
pub use self::file::FileDesc;
@ -97,8 +96,8 @@ fn last_error() -> IoError {
}
// unix has nonzero values as errors
fn mkerr_libc(ret: libc::c_int) -> IoResult<()> {
if ret != 0 {
fn mkerr_libc <Int: num::Zero>(ret: Int) -> IoResult<()> {
if !ret.is_zero() {
Err(last_error())
} else {
Ok(())
@ -117,39 +116,33 @@ fn mkerr_winbool(ret: libc::c_int) -> IoResult<()> {
#[cfg(windows)]
#[inline]
fn retry(f: || -> libc::c_int) -> libc::c_int {
loop {
match f() {
-1 if os::errno() as int == libc::WSAEINTR as int => {}
n => return n,
}
}
}
fn retry<I> (f: || -> I) -> I { f() } // PR rust-lang/rust/#17020
#[cfg(unix)]
#[inline]
fn retry(f: || -> libc::c_int) -> libc::c_int {
fn retry<I: PartialEq + num::One + Neg<I>> (f: || -> I) -> I {
let minus_one = -num::one::<I>();
loop {
match f() {
-1 if os::errno() as int == libc::EINTR as int => {}
n => return n,
}
let n = f();
if n == minus_one && os::errno() == libc::EINTR as int { }
else { return n }
}
}
fn keep_going(data: &[u8], f: |*const u8, uint| -> i64) -> i64 {
let origamt = data.len();
let mut data = data.as_ptr();
let mut amt = origamt;
while amt > 0 {
let ret = retry(|| f(data, amt) as libc::c_int);
let ret = retry(|| f(data, amt));
if ret == 0 {
break
} else if ret != -1 {
amt -= ret as uint;
data = unsafe { data.offset(ret as int) };
} else {
return ret as i64;
return ret;
}
}
return (origamt - amt) as i64;

View File

@ -13,8 +13,7 @@ use libc;
use std::mem;
use std::ptr;
use std::rt::mutex;
use std::rt::rtio;
use std::rt::rtio::{IoResult, IoError};
use std::rt::rtio::{mod, IoResult, IoError};
use std::sync::atomic;
use super::{retry, keep_going};
@ -988,9 +987,7 @@ pub fn write<T>(fd: sock_t,
write(false, inner, len)
});
} else {
ret = retry(|| {
write(false, buf.as_ptr(), buf.len()) as libc::c_int
}) as i64;
ret = retry(|| { write(false, buf.as_ptr(), buf.len()) });
if ret > 0 { written = ret as uint; }
}
}
@ -1017,7 +1014,7 @@ pub fn write<T>(fd: sock_t,
let _guard = lock();
let ptr = buf.slice_from(written).as_ptr();
let len = buf.len() - written;
match retry(|| write(deadline.is_some(), ptr, len) as libc::c_int) {
match retry(|| write(deadline.is_some(), ptr, len)) {
-1 if util::wouldblock() => {}
-1 => return Err(os::last_error()),
n => { written += n as uint; }