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
|
//! Blocking posix-based file I/O
|
||||||
|
|
||||||
use alloc::arc::Arc;
|
use alloc::arc::Arc;
|
||||||
use libc::{c_int, c_void};
|
use libc::{mod, c_int, c_void};
|
||||||
use libc;
|
|
||||||
use std::c_str::CString;
|
use std::c_str::CString;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::rt::rtio;
|
use std::rt::rtio::{mod, IoResult};
|
||||||
use std::rt::rtio::IoResult;
|
|
||||||
|
|
||||||
use io::{retry, keep_going};
|
use io::{retry, keep_going};
|
||||||
use io::util;
|
use io::util;
|
||||||
@ -55,7 +53,7 @@ impl FileDesc {
|
|||||||
let ret = retry(|| unsafe {
|
let ret = retry(|| unsafe {
|
||||||
libc::read(self.fd(),
|
libc::read(self.fd(),
|
||||||
buf.as_mut_ptr() as *mut libc::c_void,
|
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 {
|
if ret == 0 {
|
||||||
Err(util::eof())
|
Err(util::eof())
|
||||||
@ -93,7 +91,7 @@ impl rtio::RtioFileStream for FileDesc {
|
|||||||
match retry(|| unsafe {
|
match retry(|| unsafe {
|
||||||
libc::pread(self.fd(), buf.as_ptr() as *mut _,
|
libc::pread(self.fd(), buf.as_ptr() as *mut _,
|
||||||
buf.len() as libc::size_t,
|
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()),
|
-1 => Err(super::last_error()),
|
||||||
n => Ok(n as int)
|
n => Ok(n as int)
|
||||||
@ -103,7 +101,7 @@ impl rtio::RtioFileStream for FileDesc {
|
|||||||
super::mkerr_libc(retry(|| unsafe {
|
super::mkerr_libc(retry(|| unsafe {
|
||||||
libc::pwrite(self.fd(), buf.as_ptr() as *const _,
|
libc::pwrite(self.fd(), buf.as_ptr() as *const _,
|
||||||
buf.len() as libc::size_t, offset as libc::off_t)
|
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> {
|
fn seek(&mut self, pos: i64, whence: rtio::SeekStyle) -> IoResult<u64> {
|
||||||
let whence = match whence {
|
let whence = match whence {
|
||||||
|
@ -23,12 +23,11 @@
|
|||||||
|
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use libc::c_int;
|
use libc::{mod, c_int};
|
||||||
use libc;
|
|
||||||
use std::c_str::CString;
|
use std::c_str::CString;
|
||||||
use std::os;
|
use std::os;
|
||||||
use std::rt::rtio;
|
use std::rt::rtio::{mod, IoResult, IoError};
|
||||||
use std::rt::rtio::{IoResult, IoError};
|
use std::num;
|
||||||
|
|
||||||
// Local re-exports
|
// Local re-exports
|
||||||
pub use self::file::FileDesc;
|
pub use self::file::FileDesc;
|
||||||
@ -97,8 +96,8 @@ fn last_error() -> IoError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// unix has nonzero values as errors
|
// unix has nonzero values as errors
|
||||||
fn mkerr_libc(ret: libc::c_int) -> IoResult<()> {
|
fn mkerr_libc <Int: num::Zero>(ret: Int) -> IoResult<()> {
|
||||||
if ret != 0 {
|
if !ret.is_zero() {
|
||||||
Err(last_error())
|
Err(last_error())
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -117,39 +116,33 @@ fn mkerr_winbool(ret: libc::c_int) -> IoResult<()> {
|
|||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn retry(f: || -> libc::c_int) -> libc::c_int {
|
fn retry<I> (f: || -> I) -> I { f() } // PR rust-lang/rust/#17020
|
||||||
loop {
|
|
||||||
match f() {
|
|
||||||
-1 if os::errno() as int == libc::WSAEINTR as int => {}
|
|
||||||
n => return n,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
#[inline]
|
#[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 {
|
loop {
|
||||||
match f() {
|
let n = f();
|
||||||
-1 if os::errno() as int == libc::EINTR as int => {}
|
if n == minus_one && os::errno() == libc::EINTR as int { }
|
||||||
n => return n,
|
else { return n }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn keep_going(data: &[u8], f: |*const u8, uint| -> i64) -> i64 {
|
fn keep_going(data: &[u8], f: |*const u8, uint| -> i64) -> i64 {
|
||||||
let origamt = data.len();
|
let origamt = data.len();
|
||||||
let mut data = data.as_ptr();
|
let mut data = data.as_ptr();
|
||||||
let mut amt = origamt;
|
let mut amt = origamt;
|
||||||
while amt > 0 {
|
while amt > 0 {
|
||||||
let ret = retry(|| f(data, amt) as libc::c_int);
|
let ret = retry(|| f(data, amt));
|
||||||
if ret == 0 {
|
if ret == 0 {
|
||||||
break
|
break
|
||||||
} else if ret != -1 {
|
} else if ret != -1 {
|
||||||
amt -= ret as uint;
|
amt -= ret as uint;
|
||||||
data = unsafe { data.offset(ret as int) };
|
data = unsafe { data.offset(ret as int) };
|
||||||
} else {
|
} else {
|
||||||
return ret as i64;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (origamt - amt) as i64;
|
return (origamt - amt) as i64;
|
||||||
|
@ -13,8 +13,7 @@ use libc;
|
|||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::rt::mutex;
|
use std::rt::mutex;
|
||||||
use std::rt::rtio;
|
use std::rt::rtio::{mod, IoResult, IoError};
|
||||||
use std::rt::rtio::{IoResult, IoError};
|
|
||||||
use std::sync::atomic;
|
use std::sync::atomic;
|
||||||
|
|
||||||
use super::{retry, keep_going};
|
use super::{retry, keep_going};
|
||||||
@ -988,9 +987,7 @@ pub fn write<T>(fd: sock_t,
|
|||||||
write(false, inner, len)
|
write(false, inner, len)
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
ret = retry(|| {
|
ret = retry(|| { write(false, buf.as_ptr(), buf.len()) });
|
||||||
write(false, buf.as_ptr(), buf.len()) as libc::c_int
|
|
||||||
}) as i64;
|
|
||||||
if ret > 0 { written = ret as uint; }
|
if ret > 0 { written = ret as uint; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1017,7 +1014,7 @@ pub fn write<T>(fd: sock_t,
|
|||||||
let _guard = lock();
|
let _guard = lock();
|
||||||
let ptr = buf.slice_from(written).as_ptr();
|
let ptr = buf.slice_from(written).as_ptr();
|
||||||
let len = buf.len() - written;
|
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 if util::wouldblock() => {}
|
||||||
-1 => return Err(os::last_error()),
|
-1 => return Err(os::last_error()),
|
||||||
n => { written += n as uint; }
|
n => { written += n as uint; }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user