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:
parent
67b97ab6d2
commit
52e99cbcaa
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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; }
|
||||
|
Loading…
Reference in New Issue
Block a user