native: Deal with the rtio changes

This commit is contained in:
Alex Crichton 2014-06-04 00:00:49 -07:00
parent da2293c6f6
commit 51348b068b
10 changed files with 313 additions and 318 deletions

View File

@ -8,21 +8,23 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use ai = std::io::net::addrinfo;
use libc::{c_char, c_int};
use libc;
use std::c_str::CString;
use std::io::IoError;
use std::mem;
use std::ptr::{null, mut_null};
use std::rt::rtio;
use std::rt::rtio::IoError;
use super::net::sockaddr_to_addr;
use super::net;
pub struct GetAddrInfoRequest;
impl GetAddrInfoRequest {
pub fn run(host: Option<&str>, servname: Option<&str>,
hint: Option<ai::Hint>) -> Result<Vec<ai::Info>, IoError> {
hint: Option<rtio::AddrinfoHint>)
-> Result<Vec<rtio::AddrinfoInfo>, IoError>
{
assert!(host.is_some() || servname.is_some());
let c_host = host.map_or(unsafe { CString::new(null(), true) }, |x| x.to_c_str());
@ -61,16 +63,16 @@ impl GetAddrInfoRequest {
let mut rp = res;
while rp.is_not_null() {
unsafe {
let addr = match sockaddr_to_addr(mem::transmute((*rp).ai_addr),
(*rp).ai_addrlen as uint) {
let addr = match net::sockaddr_to_addr(mem::transmute((*rp).ai_addr),
(*rp).ai_addrlen as uint) {
Ok(a) => a,
Err(e) => return Err(e)
};
addrs.push(ai::Info {
addrs.push(rtio::AddrinfoInfo {
address: addr,
family: (*rp).ai_family as uint,
socktype: None,
protocol: None,
socktype: 0,
protocol: 0,
flags: (*rp).ai_flags as uint
});
@ -96,21 +98,18 @@ extern "system" {
#[cfg(windows)]
fn get_error(_: c_int) -> IoError {
unsafe {
IoError::from_errno(WSAGetLastError() as uint, true)
}
net::last_error()
}
#[cfg(not(windows))]
fn get_error(s: c_int) -> IoError {
use std::io;
let err_str = unsafe {
CString::new(gai_strerror(s), false).as_str().unwrap().to_string()
};
IoError {
kind: io::OtherIoError,
desc: "unable to resolve host",
code: s as uint,
extra: 0,
detail: Some(err_str),
}
}

View File

@ -14,12 +14,12 @@ use alloc::arc::Arc;
use libc::{c_int, c_void};
use libc;
use std::c_str::CString;
use std::io::IoError;
use std::io;
use std::mem;
use std::rt::rtio;
use std::rt::rtio::IoResult;
use io::{IoResult, retry, keep_going};
use io::{retry, keep_going};
use io::util;
pub type fd_t = libc::c_int;
@ -51,21 +51,21 @@ impl FileDesc {
// FIXME(#10465) these functions should not be public, but anything in
// native::io wanting to use them is forced to have all the
// rtio traits in scope
pub fn inner_read(&mut self, buf: &mut [u8]) -> Result<uint, IoError> {
pub fn inner_read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
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
});
if ret == 0 {
Err(io::standard_error(io::EndOfFile))
Err(util::eof())
} else if ret < 0 {
Err(super::last_error())
} else {
Ok(ret as uint)
}
}
pub fn inner_write(&mut self, buf: &[u8]) -> Result<(), IoError> {
pub fn inner_write(&mut self, buf: &[u8]) -> IoResult<()> {
let ret = keep_going(buf, |buf, len| {
unsafe {
libc::write(self.fd(), buf as *libc::c_void,
@ -82,26 +82,14 @@ impl FileDesc {
pub fn fd(&self) -> fd_t { self.inner.fd }
}
impl io::Reader for FileDesc {
fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
self.inner_read(buf)
}
}
impl io::Writer for FileDesc {
fn write(&mut self, buf: &[u8]) -> io::IoResult<()> {
self.inner_write(buf)
}
}
impl rtio::RtioFileStream for FileDesc {
fn read(&mut self, buf: &mut [u8]) -> Result<int, IoError> {
fn read(&mut self, buf: &mut [u8]) -> IoResult<int> {
self.inner_read(buf).map(|i| i as int)
}
fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
self.inner_write(buf)
}
fn pread(&mut self, buf: &mut [u8], offset: u64) -> Result<int, IoError> {
fn pread(&mut self, buf: &mut [u8], offset: u64) -> IoResult<int> {
match retry(|| unsafe {
libc::pread(self.fd(), buf.as_ptr() as *libc::c_void,
buf.len() as libc::size_t,
@ -111,17 +99,17 @@ impl rtio::RtioFileStream for FileDesc {
n => Ok(n as int)
}
}
fn pwrite(&mut self, buf: &[u8], offset: u64) -> Result<(), IoError> {
fn pwrite(&mut self, buf: &[u8], offset: u64) -> IoResult<()> {
super::mkerr_libc(retry(|| unsafe {
libc::pwrite(self.fd(), buf.as_ptr() as *libc::c_void,
buf.len() as libc::size_t, offset as libc::off_t)
} as c_int))
}
fn seek(&mut self, pos: i64, whence: io::SeekStyle) -> Result<u64, IoError> {
fn seek(&mut self, pos: i64, whence: rtio::SeekStyle) -> IoResult<u64> {
let whence = match whence {
io::SeekSet => libc::SEEK_SET,
io::SeekEnd => libc::SEEK_END,
io::SeekCur => libc::SEEK_CUR,
rtio::SeekSet => libc::SEEK_SET,
rtio::SeekEnd => libc::SEEK_END,
rtio::SeekCur => libc::SEEK_CUR,
};
let n = unsafe { libc::lseek(self.fd(), pos as libc::off_t, whence) };
if n < 0 {
@ -130,7 +118,7 @@ impl rtio::RtioFileStream for FileDesc {
Ok(n as u64)
}
}
fn tell(&self) -> Result<u64, IoError> {
fn tell(&self) -> IoResult<u64> {
let n = unsafe { libc::lseek(self.fd(), 0, libc::SEEK_CUR) };
if n < 0 {
Err(super::last_error())
@ -138,10 +126,10 @@ impl rtio::RtioFileStream for FileDesc {
Ok(n as u64)
}
}
fn fsync(&mut self) -> Result<(), IoError> {
fn fsync(&mut self) -> IoResult<()> {
super::mkerr_libc(retry(|| unsafe { libc::fsync(self.fd()) }))
}
fn datasync(&mut self) -> Result<(), IoError> {
fn datasync(&mut self) -> IoResult<()> {
return super::mkerr_libc(os_datasync(self.fd()));
#[cfg(target_os = "macos")]
@ -157,13 +145,13 @@ impl rtio::RtioFileStream for FileDesc {
retry(|| unsafe { libc::fsync(fd) })
}
}
fn truncate(&mut self, offset: i64) -> Result<(), IoError> {
fn truncate(&mut self, offset: i64) -> IoResult<()> {
super::mkerr_libc(retry(|| unsafe {
libc::ftruncate(self.fd(), offset as libc::off_t)
}))
}
fn fstat(&mut self) -> IoResult<io::FileStat> {
fn fstat(&mut self) -> IoResult<rtio::FileStat> {
let mut stat: libc::stat = unsafe { mem::zeroed() };
match retry(|| unsafe { libc::fstat(self.fd(), &mut stat) }) {
0 => Ok(mkstat(&stat)),
@ -173,10 +161,10 @@ impl rtio::RtioFileStream for FileDesc {
}
impl rtio::RtioPipe for FileDesc {
fn read(&mut self, buf: &mut [u8]) -> Result<uint, IoError> {
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
self.inner_read(buf)
}
fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
self.inner_write(buf)
}
fn clone(&self) -> Box<rtio::RtioPipe:Send> {
@ -187,11 +175,11 @@ impl rtio::RtioPipe for FileDesc {
// impact on the std::io primitives, this is never called via
// std::io::PipeStream. If the functionality is exposed in the future, then
// these methods will need to be implemented.
fn close_read(&mut self) -> Result<(), IoError> {
Err(io::standard_error(io::InvalidInput))
fn close_read(&mut self) -> IoResult<()> {
Err(super::unimpl())
}
fn close_write(&mut self) -> Result<(), IoError> {
Err(io::standard_error(io::InvalidInput))
fn close_write(&mut self) -> IoResult<()> {
Err(super::unimpl())
}
fn set_timeout(&mut self, _t: Option<u64>) {}
fn set_read_timeout(&mut self, _t: Option<u64>) {}
@ -199,16 +187,16 @@ impl rtio::RtioPipe for FileDesc {
}
impl rtio::RtioTTY for FileDesc {
fn read(&mut self, buf: &mut [u8]) -> Result<uint, IoError> {
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
self.inner_read(buf)
}
fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
self.inner_write(buf)
}
fn set_raw(&mut self, _raw: bool) -> Result<(), IoError> {
fn set_raw(&mut self, _raw: bool) -> IoResult<()> {
Err(super::unimpl())
}
fn get_winsize(&mut self) -> Result<(int, int), IoError> {
fn get_winsize(&mut self) -> IoResult<(int, int)> {
Err(super::unimpl())
}
fn isatty(&self) -> bool { false }
@ -249,13 +237,13 @@ impl CFile {
}
}
pub fn flush(&mut self) -> Result<(), IoError> {
pub fn flush(&mut self) -> IoResult<()> {
super::mkerr_libc(retry(|| unsafe { libc::fflush(self.file) }))
}
}
impl rtio::RtioFileStream for CFile {
fn read(&mut self, buf: &mut [u8]) -> Result<int, IoError> {
fn read(&mut self, buf: &mut [u8]) -> IoResult<int> {
let ret = keep_going(buf, |buf, len| {
unsafe {
libc::fread(buf as *mut libc::c_void, 1, len as libc::size_t,
@ -263,7 +251,7 @@ impl rtio::RtioFileStream for CFile {
}
});
if ret == 0 {
Err(io::standard_error(io::EndOfFile))
Err(util::eof())
} else if ret < 0 {
Err(super::last_error())
} else {
@ -271,7 +259,7 @@ impl rtio::RtioFileStream for CFile {
}
}
fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
let ret = keep_going(buf, |buf, len| {
unsafe {
libc::fwrite(buf as *libc::c_void, 1, len as libc::size_t,
@ -285,17 +273,17 @@ impl rtio::RtioFileStream for CFile {
}
}
fn pread(&mut self, buf: &mut [u8], offset: u64) -> Result<int, IoError> {
fn pread(&mut self, buf: &mut [u8], offset: u64) -> IoResult<int> {
self.flush().and_then(|()| self.fd.pread(buf, offset))
}
fn pwrite(&mut self, buf: &[u8], offset: u64) -> Result<(), IoError> {
fn pwrite(&mut self, buf: &[u8], offset: u64) -> IoResult<()> {
self.flush().and_then(|()| self.fd.pwrite(buf, offset))
}
fn seek(&mut self, pos: i64, style: io::SeekStyle) -> Result<u64, IoError> {
fn seek(&mut self, pos: i64, style: rtio::SeekStyle) -> IoResult<u64> {
let whence = match style {
io::SeekSet => libc::SEEK_SET,
io::SeekEnd => libc::SEEK_END,
io::SeekCur => libc::SEEK_CUR,
rtio::SeekSet => libc::SEEK_SET,
rtio::SeekEnd => libc::SEEK_END,
rtio::SeekCur => libc::SEEK_CUR,
};
let n = unsafe { libc::fseek(self.file, pos as libc::c_long, whence) };
if n < 0 {
@ -304,7 +292,7 @@ impl rtio::RtioFileStream for CFile {
Ok(n as u64)
}
}
fn tell(&self) -> Result<u64, IoError> {
fn tell(&self) -> IoResult<u64> {
let ret = unsafe { libc::ftell(self.file) };
if ret < 0 {
Err(super::last_error())
@ -312,17 +300,17 @@ impl rtio::RtioFileStream for CFile {
Ok(ret as u64)
}
}
fn fsync(&mut self) -> Result<(), IoError> {
fn fsync(&mut self) -> IoResult<()> {
self.flush().and_then(|()| self.fd.fsync())
}
fn datasync(&mut self) -> Result<(), IoError> {
fn datasync(&mut self) -> IoResult<()> {
self.flush().and_then(|()| self.fd.fsync())
}
fn truncate(&mut self, offset: i64) -> Result<(), IoError> {
fn truncate(&mut self, offset: i64) -> IoResult<()> {
self.flush().and_then(|()| self.fd.truncate(offset))
}
fn fstat(&mut self) -> IoResult<io::FileStat> {
fn fstat(&mut self) -> IoResult<rtio::FileStat> {
self.flush().and_then(|()| self.fd.fstat())
}
}
@ -333,20 +321,21 @@ impl Drop for CFile {
}
}
pub fn open(path: &CString, fm: io::FileMode, fa: io::FileAccess)
-> IoResult<FileDesc> {
pub fn open(path: &CString, fm: rtio::FileMode, fa: rtio::FileAccess)
-> IoResult<FileDesc>
{
let flags = match fm {
io::Open => 0,
io::Append => libc::O_APPEND,
io::Truncate => libc::O_TRUNC,
rtio::Open => 0,
rtio::Append => libc::O_APPEND,
rtio::Truncate => libc::O_TRUNC,
};
// Opening with a write permission must silently create the file.
let (flags, mode) = match fa {
io::Read => (flags | libc::O_RDONLY, 0),
io::Write => (flags | libc::O_WRONLY | libc::O_CREAT,
libc::S_IRUSR | libc::S_IWUSR),
io::ReadWrite => (flags | libc::O_RDWR | libc::O_CREAT,
libc::S_IRUSR | libc::S_IWUSR),
rtio::Read => (flags | libc::O_RDONLY, 0),
rtio::Write => (flags | libc::O_WRONLY | libc::O_CREAT,
libc::S_IRUSR | libc::S_IWUSR),
rtio::ReadWrite => (flags | libc::O_RDWR | libc::O_CREAT,
libc::S_IRUSR | libc::S_IWUSR),
};
match retry(|| unsafe { libc::open(path.with_ref(|p| p), flags, mode) }) {
@ -355,9 +344,9 @@ pub fn open(path: &CString, fm: io::FileMode, fa: io::FileAccess)
}
}
pub fn mkdir(p: &CString, mode: io::FilePermission) -> IoResult<()> {
pub fn mkdir(p: &CString, mode: uint) -> IoResult<()> {
super::mkerr_libc(retry(|| unsafe {
libc::mkdir(p.with_ref(|p| p), mode.bits() as libc::mode_t)
libc::mkdir(p.with_ref(|p| p), mode as libc::mode_t)
}))
}
@ -412,9 +401,9 @@ pub fn rename(old: &CString, new: &CString) -> IoResult<()> {
}))
}
pub fn chmod(p: &CString, mode: io::FilePermission) -> IoResult<()> {
pub fn chmod(p: &CString, mode: uint) -> IoResult<()> {
super::mkerr_libc(retry(|| unsafe {
libc::chmod(p.with_ref(|p| p), mode.bits() as libc::mode_t)
libc::chmod(p.with_ref(|p| p), mode as libc::mode_t)
}))
}
@ -463,19 +452,10 @@ pub fn link(src: &CString, dst: &CString) -> IoResult<()> {
}))
}
fn mkstat(stat: &libc::stat) -> io::FileStat {
fn mkstat(stat: &libc::stat) -> rtio::FileStat {
// FileStat times are in milliseconds
fn mktime(secs: u64, nsecs: u64) -> u64 { secs * 1000 + nsecs / 1000000 }
let kind = match (stat.st_mode as c_int) & libc::S_IFMT {
libc::S_IFREG => io::TypeFile,
libc::S_IFDIR => io::TypeDirectory,
libc::S_IFIFO => io::TypeNamedPipe,
libc::S_IFBLK => io::TypeBlockSpecial,
libc::S_IFLNK => io::TypeSymlink,
_ => io::TypeUnknown,
};
#[cfg(not(target_os = "linux"), not(target_os = "android"))]
fn flags(stat: &libc::stat) -> u64 { stat.st_flags as u64 }
#[cfg(target_os = "linux")] #[cfg(target_os = "android")]
@ -486,29 +466,27 @@ fn mkstat(stat: &libc::stat) -> io::FileStat {
#[cfg(target_os = "linux")] #[cfg(target_os = "android")]
fn gen(_stat: &libc::stat) -> u64 { 0 }
io::FileStat {
rtio::FileStat {
size: stat.st_size as u64,
kind: kind,
perm: io::FilePermission::from_bits_truncate(stat.st_mode as u32),
kind: stat.st_mode as u64,
perm: stat.st_mode as u64,
created: mktime(stat.st_ctime as u64, stat.st_ctime_nsec as u64),
modified: mktime(stat.st_mtime as u64, stat.st_mtime_nsec as u64),
accessed: mktime(stat.st_atime as u64, stat.st_atime_nsec as u64),
unstable: io::UnstableFileStat {
device: stat.st_dev as u64,
inode: stat.st_ino as u64,
rdev: stat.st_rdev as u64,
nlink: stat.st_nlink as u64,
uid: stat.st_uid as u64,
gid: stat.st_gid as u64,
blksize: stat.st_blksize as u64,
blocks: stat.st_blocks as u64,
flags: flags(stat),
gen: gen(stat),
}
device: stat.st_dev as u64,
inode: stat.st_ino as u64,
rdev: stat.st_rdev as u64,
nlink: stat.st_nlink as u64,
uid: stat.st_uid as u64,
gid: stat.st_gid as u64,
blksize: stat.st_blksize as u64,
blocks: stat.st_blocks as u64,
flags: flags(stat),
gen: gen(stat),
}
}
pub fn stat(p: &CString) -> IoResult<io::FileStat> {
pub fn stat(p: &CString) -> IoResult<rtio::FileStat> {
let mut stat: libc::stat = unsafe { mem::zeroed() };
match retry(|| unsafe { libc::stat(p.with_ref(|p| p), &mut stat) }) {
0 => Ok(mkstat(&stat)),
@ -516,7 +494,7 @@ pub fn stat(p: &CString) -> IoResult<io::FileStat> {
}
}
pub fn lstat(p: &CString) -> IoResult<io::FileStat> {
pub fn lstat(p: &CString) -> IoResult<rtio::FileStat> {
let mut stat: libc::stat = unsafe { mem::zeroed() };
match retry(|| unsafe { libc::lstat(p.with_ref(|p| p), &mut stat) }) {
0 => Ok(mkstat(&stat)),
@ -537,10 +515,9 @@ pub fn utime(p: &CString, atime: u64, mtime: u64) -> IoResult<()> {
#[cfg(test)]
mod tests {
use super::{CFile, FileDesc};
use std::io;
use libc;
use std::os;
use std::rt::rtio::RtioFileStream;
use std::rt::rtio::{RtioFileStream, SeekSet};
#[ignore(cfg(target_os = "freebsd"))] // hmm, maybe pipes have a tiny buffer
#[test]
@ -551,7 +528,7 @@ mod tests {
let mut reader = FileDesc::new(input, true);
let mut writer = FileDesc::new(out, true);
writer.inner_write(bytes!("test")).unwrap();
writer.inner_write(bytes!("test")).ok().unwrap();
let mut buf = [0u8, ..4];
match reader.inner_read(buf) {
Ok(4) => {
@ -574,9 +551,9 @@ mod tests {
assert!(!f.is_null());
let mut file = CFile::new(f);
file.write(bytes!("test")).unwrap();
file.write(bytes!("test")).ok().unwrap();
let mut buf = [0u8, ..4];
let _ = file.seek(0, io::SeekSet).unwrap();
let _ = file.seek(0, SeekSet).ok().unwrap();
match file.read(buf) {
Ok(4) => {
assert_eq!(buf[0], 't' as u8);

View File

@ -24,9 +24,9 @@
use std::mem;
use std::rt::bookkeeping;
use std::rt::mutex::StaticNativeMutex;
use std::rt;
use std::ty::Unsafe;
use std::unstable::mutex::StaticNativeMutex;
use task;
@ -57,7 +57,7 @@ pub struct Helper<M> {
macro_rules! helper_init( (static mut $name:ident: Helper<$m:ty>) => (
static mut $name: Helper<$m> = Helper {
lock: ::std::unstable::mutex::NATIVE_MUTEX_INIT,
lock: ::std::rt::mutex::NATIVE_MUTEX_INIT,
chan: ::std::ty::Unsafe {
value: 0 as *mut Sender<$m>,
marker1: ::std::kinds::marker::InvariantType,
@ -163,7 +163,7 @@ mod imp {
}
pub fn signal(fd: libc::c_int) {
FileDesc::new(fd, false).inner_write([0]).unwrap();
FileDesc::new(fd, false).inner_write([0]).ok().unwrap();
}
pub fn close(fd: libc::c_int) {

View File

@ -26,16 +26,9 @@
use libc::c_int;
use libc;
use std::c_str::CString;
use std::io;
use std::io::IoError;
use std::io::net::ip::SocketAddr;
use std::io::signal::Signum;
use std::os;
use std::rt::rtio;
use std::rt::rtio::{RtioTcpStream, RtioTcpListener, RtioUdpSocket};
use std::rt::rtio::{RtioUnixListener, RtioPipe, RtioFileStream, RtioProcess};
use std::rt::rtio::{RtioSignal, RtioTTY, CloseBehavior, RtioTimer, ProcessConfig};
use ai = std::io::net::addrinfo;
use std::rt::rtio::{IoResult, IoError};
// Local re-exports
pub use self::file::FileDesc;
@ -78,18 +71,23 @@ pub mod pipe;
#[cfg(unix)] #[path = "c_unix.rs"] mod c;
#[cfg(windows)] #[path = "c_win32.rs"] mod c;
pub type IoResult<T> = Result<T, IoError>;
fn unimpl() -> IoError {
#[cfg(unix)] use ERROR = libc::ENOSYS;
#[cfg(windows)] use ERROR = libc::ERROR_CALL_NOT_IMPLEMENTED;
IoError {
kind: io::IoUnavailable,
desc: "unimplemented I/O interface",
code: ERROR as uint,
extra: 0,
detail: None,
}
}
fn last_error() -> IoError {
IoError::last_error()
let errno = os::errno() as uint;
IoError {
code: os::errno() as uint,
extra: 0,
detail: Some(os::error_string(errno)),
}
}
// unix has nonzero values as errors
@ -166,64 +164,70 @@ impl IoFactory {
impl rtio::IoFactory for IoFactory {
// networking
fn tcp_connect(&mut self, addr: SocketAddr,
timeout: Option<u64>) -> IoResult<Box<RtioTcpStream:Send>> {
fn tcp_connect(&mut self, addr: rtio::SocketAddr,
timeout: Option<u64>)
-> IoResult<Box<rtio::RtioTcpStream:Send>>
{
net::TcpStream::connect(addr, timeout).map(|s| {
box s as Box<RtioTcpStream:Send>
box s as Box<rtio::RtioTcpStream:Send>
})
}
fn tcp_bind(&mut self, addr: SocketAddr)
-> IoResult<Box<RtioTcpListener:Send>> {
fn tcp_bind(&mut self, addr: rtio::SocketAddr)
-> IoResult<Box<rtio::RtioTcpListener:Send>> {
net::TcpListener::bind(addr).map(|s| {
box s as Box<RtioTcpListener:Send>
box s as Box<rtio::RtioTcpListener:Send>
})
}
fn udp_bind(&mut self, addr: SocketAddr)
-> IoResult<Box<RtioUdpSocket:Send>> {
net::UdpSocket::bind(addr).map(|u| box u as Box<RtioUdpSocket:Send>)
fn udp_bind(&mut self, addr: rtio::SocketAddr)
-> IoResult<Box<rtio::RtioUdpSocket:Send>> {
net::UdpSocket::bind(addr).map(|u| {
box u as Box<rtio::RtioUdpSocket:Send>
})
}
fn unix_bind(&mut self, path: &CString)
-> IoResult<Box<RtioUnixListener:Send>> {
-> IoResult<Box<rtio::RtioUnixListener:Send>> {
pipe::UnixListener::bind(path).map(|s| {
box s as Box<RtioUnixListener:Send>
box s as Box<rtio::RtioUnixListener:Send>
})
}
fn unix_connect(&mut self, path: &CString,
timeout: Option<u64>) -> IoResult<Box<RtioPipe:Send>> {
timeout: Option<u64>) -> IoResult<Box<rtio::RtioPipe:Send>> {
pipe::UnixStream::connect(path, timeout).map(|s| {
box s as Box<RtioPipe:Send>
box s as Box<rtio::RtioPipe:Send>
})
}
fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>,
hint: Option<ai::Hint>) -> IoResult<Vec<ai::Info>> {
hint: Option<rtio::AddrinfoHint>)
-> IoResult<Vec<rtio::AddrinfoInfo>>
{
addrinfo::GetAddrInfoRequest::run(host, servname, hint)
}
// filesystem operations
fn fs_from_raw_fd(&mut self, fd: c_int, close: CloseBehavior)
-> Box<RtioFileStream:Send> {
fn fs_from_raw_fd(&mut self, fd: c_int, close: rtio::CloseBehavior)
-> Box<rtio::RtioFileStream:Send> {
let close = match close {
rtio::CloseSynchronously | rtio::CloseAsynchronously => true,
rtio::DontClose => false
};
box file::FileDesc::new(fd, close) as Box<RtioFileStream:Send>
box file::FileDesc::new(fd, close) as Box<rtio::RtioFileStream:Send>
}
fn fs_open(&mut self, path: &CString, fm: io::FileMode, fa: io::FileAccess)
-> IoResult<Box<RtioFileStream:Send>> {
file::open(path, fm, fa).map(|fd| box fd as Box<RtioFileStream:Send>)
fn fs_open(&mut self, path: &CString, fm: rtio::FileMode,
fa: rtio::FileAccess)
-> IoResult<Box<rtio::RtioFileStream:Send>>
{
file::open(path, fm, fa).map(|fd| box fd as Box<rtio::RtioFileStream:Send>)
}
fn fs_unlink(&mut self, path: &CString) -> IoResult<()> {
file::unlink(path)
}
fn fs_stat(&mut self, path: &CString) -> IoResult<io::FileStat> {
fn fs_stat(&mut self, path: &CString) -> IoResult<rtio::FileStat> {
file::stat(path)
}
fn fs_mkdir(&mut self, path: &CString,
mode: io::FilePermission) -> IoResult<()> {
fn fs_mkdir(&mut self, path: &CString, mode: uint) -> IoResult<()> {
file::mkdir(path, mode)
}
fn fs_chmod(&mut self, path: &CString,
mode: io::FilePermission) -> IoResult<()> {
fn fs_chmod(&mut self, path: &CString, mode: uint) -> IoResult<()> {
file::chmod(path, mode)
}
fn fs_rmdir(&mut self, path: &CString) -> IoResult<()> {
@ -235,7 +239,7 @@ impl rtio::IoFactory for IoFactory {
fn fs_readdir(&mut self, path: &CString, _flags: c_int) -> IoResult<Vec<CString>> {
file::readdir(path)
}
fn fs_lstat(&mut self, path: &CString) -> IoResult<io::FileStat> {
fn fs_lstat(&mut self, path: &CString) -> IoResult<rtio::FileStat> {
file::lstat(path)
}
fn fs_chown(&mut self, path: &CString, uid: int, gid: int) -> IoResult<()> {
@ -256,39 +260,41 @@ impl rtio::IoFactory for IoFactory {
}
// misc
fn timer_init(&mut self) -> IoResult<Box<RtioTimer:Send>> {
timer::Timer::new().map(|t| box t as Box<RtioTimer:Send>)
fn timer_init(&mut self) -> IoResult<Box<rtio::RtioTimer:Send>> {
timer::Timer::new().map(|t| box t as Box<rtio::RtioTimer:Send>)
}
fn spawn(&mut self, cfg: ProcessConfig)
-> IoResult<(Box<RtioProcess:Send>,
Vec<Option<Box<RtioPipe:Send>>>)> {
fn spawn(&mut self, cfg: rtio::ProcessConfig)
-> IoResult<(Box<rtio::RtioProcess:Send>,
Vec<Option<Box<rtio::RtioPipe:Send>>>)> {
process::Process::spawn(cfg).map(|(p, io)| {
(box p as Box<RtioProcess:Send>,
(box p as Box<rtio::RtioProcess:Send>,
io.move_iter().map(|p| p.map(|p| {
box p as Box<RtioPipe:Send>
box p as Box<rtio::RtioPipe:Send>
})).collect())
})
}
fn kill(&mut self, pid: libc::pid_t, signum: int) -> IoResult<()> {
process::Process::kill(pid, signum)
}
fn pipe_open(&mut self, fd: c_int) -> IoResult<Box<RtioPipe:Send>> {
Ok(box file::FileDesc::new(fd, true) as Box<RtioPipe:Send>)
fn pipe_open(&mut self, fd: c_int) -> IoResult<Box<rtio::RtioPipe:Send>> {
Ok(box file::FileDesc::new(fd, true) as Box<rtio::RtioPipe:Send>)
}
fn tty_open(&mut self, fd: c_int, _readable: bool)
-> IoResult<Box<RtioTTY:Send>> {
-> IoResult<Box<rtio::RtioTTY:Send>> {
#[cfg(unix)] use ERROR = libc::ENOTTY;
#[cfg(windows)] use ERROR = libc::ERROR_INVALID_HANDLE;
if unsafe { libc::isatty(fd) } != 0 {
Ok(box file::FileDesc::new(fd, true) as Box<RtioTTY:Send>)
Ok(box file::FileDesc::new(fd, true) as Box<rtio::RtioTTY:Send>)
} else {
Err(IoError {
kind: io::MismatchedFileTypeForOperation,
desc: "file descriptor is not a TTY",
code: ERROR as uint,
extra: 0,
detail: None,
})
}
}
fn signal(&mut self, _signal: Signum, _channel: Sender<Signum>)
-> IoResult<Box<RtioSignal:Send>> {
fn signal(&mut self, _signal: int, _cb: Box<rtio::Callback>)
-> IoResult<Box<rtio::RtioSignal:Send>> {
Err(unimpl())
}
}

View File

@ -10,13 +10,12 @@
use alloc::arc::Arc;
use libc;
use std::io::net::ip;
use std::io;
use std::mem;
use std::rt::mutex;
use std::rt::rtio;
use std::unstable::mutex;
use std::rt::rtio::{IoResult, IoError};
use super::{IoResult, retry, keep_going};
use super::{retry, keep_going};
use super::c;
use super::util;
@ -39,9 +38,9 @@ enum InAddr {
In6Addr(libc::in6_addr),
}
fn ip_to_inaddr(ip: ip::IpAddr) -> InAddr {
fn ip_to_inaddr(ip: rtio::IpAddr) -> InAddr {
match ip {
ip::Ipv4Addr(a, b, c, d) => {
rtio::Ipv4Addr(a, b, c, d) => {
let ip = (a as u32 << 24) |
(b as u32 << 16) |
(c as u32 << 8) |
@ -50,7 +49,7 @@ fn ip_to_inaddr(ip: ip::IpAddr) -> InAddr {
s_addr: mem::from_be32(ip)
})
}
ip::Ipv6Addr(a, b, c, d, e, f, g, h) => {
rtio::Ipv6Addr(a, b, c, d, e, f, g, h) => {
In6Addr(libc::in6_addr {
s6_addr: [
htons(a),
@ -67,7 +66,7 @@ fn ip_to_inaddr(ip: ip::IpAddr) -> InAddr {
}
}
fn addr_to_sockaddr(addr: ip::SocketAddr) -> (libc::sockaddr_storage, uint) {
fn addr_to_sockaddr(addr: rtio::SocketAddr) -> (libc::sockaddr_storage, uint) {
unsafe {
let storage: libc::sockaddr_storage = mem::zeroed();
let len = match ip_to_inaddr(addr.ip) {
@ -90,11 +89,11 @@ fn addr_to_sockaddr(addr: ip::SocketAddr) -> (libc::sockaddr_storage, uint) {
}
}
fn socket(addr: ip::SocketAddr, ty: libc::c_int) -> IoResult<sock_t> {
fn socket(addr: rtio::SocketAddr, ty: libc::c_int) -> IoResult<sock_t> {
unsafe {
let fam = match addr.ip {
ip::Ipv4Addr(..) => libc::AF_INET,
ip::Ipv6Addr(..) => libc::AF_INET6,
rtio::Ipv4Addr(..) => libc::AF_INET,
rtio::Ipv6Addr(..) => libc::AF_INET6,
};
match libc::socket(fam, ty, 0) {
-1 => Err(super::last_error()),
@ -136,12 +135,16 @@ pub fn getsockopt<T: Copy>(fd: sock_t, opt: libc::c_int,
}
#[cfg(windows)]
fn last_error() -> io::IoError {
io::IoError::from_errno(unsafe { c::WSAGetLastError() } as uint, true)
fn last_error() -> IoError {
let code = unsafe { c::WSAGetLastError() as uint };
IoError {
code: code,
detail: Some(os::error_string(code)),
}
}
#[cfg(not(windows))]
fn last_error() -> io::IoError {
fn last_error() -> IoError {
super::last_error()
}
@ -151,7 +154,7 @@ fn last_error() -> io::IoError {
fn sockname(fd: sock_t,
f: unsafe extern "system" fn(sock_t, *mut libc::sockaddr,
*mut libc::socklen_t) -> libc::c_int)
-> IoResult<ip::SocketAddr>
-> IoResult<rtio::SocketAddr>
{
let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
let mut len = mem::size_of::<libc::sockaddr_storage>() as libc::socklen_t;
@ -168,7 +171,7 @@ fn sockname(fd: sock_t,
}
pub fn sockaddr_to_addr(storage: &libc::sockaddr_storage,
len: uint) -> IoResult<ip::SocketAddr> {
len: uint) -> IoResult<rtio::SocketAddr> {
match storage.ss_family as libc::c_int {
libc::AF_INET => {
assert!(len as uint >= mem::size_of::<libc::sockaddr_in>());
@ -180,8 +183,8 @@ pub fn sockaddr_to_addr(storage: &libc::sockaddr_storage,
let b = (ip >> 16) as u8;
let c = (ip >> 8) as u8;
let d = (ip >> 0) as u8;
Ok(ip::SocketAddr {
ip: ip::Ipv4Addr(a, b, c, d),
Ok(rtio::SocketAddr {
ip: rtio::Ipv4Addr(a, b, c, d),
port: ntohs(storage.sin_port),
})
}
@ -198,13 +201,19 @@ pub fn sockaddr_to_addr(storage: &libc::sockaddr_storage,
let f = ntohs(storage.sin6_addr.s6_addr[5]);
let g = ntohs(storage.sin6_addr.s6_addr[6]);
let h = ntohs(storage.sin6_addr.s6_addr[7]);
Ok(ip::SocketAddr {
ip: ip::Ipv6Addr(a, b, c, d, e, f, g, h),
Ok(rtio::SocketAddr {
ip: rtio::Ipv6Addr(a, b, c, d, e, f, g, h),
port: ntohs(storage.sin6_port),
})
}
_ => {
Err(io::standard_error(io::OtherIoError))
#[cfg(unix)] use ERROR = libc::EINVAL;
#[cfg(windows)] use ERROR = libc::WSAEINVAL;
Err(IoError {
code: ERROR as uint,
extra: 0,
detail: None,
})
}
}
}
@ -258,7 +267,7 @@ impl Inner {
}
impl TcpStream {
pub fn connect(addr: ip::SocketAddr,
pub fn connect(addr: rtio::SocketAddr,
timeout: Option<u64>) -> IoResult<TcpStream> {
let fd = try!(socket(addr, libc::SOCK_STREAM));
let ret = TcpStream::new(Inner::new(fd));
@ -366,7 +375,7 @@ impl rtio::RtioTcpStream for TcpStream {
Err(e) => Err(e)
}
}
fn peer_name(&mut self) -> IoResult<ip::SocketAddr> {
fn peer_name(&mut self) -> IoResult<rtio::SocketAddr> {
sockname(self.fd(), libc::getpeername)
}
fn control_congestion(&mut self) -> IoResult<()> {
@ -411,7 +420,7 @@ impl rtio::RtioTcpStream for TcpStream {
}
impl rtio::RtioSocket for TcpStream {
fn socket_name(&mut self) -> IoResult<ip::SocketAddr> {
fn socket_name(&mut self) -> IoResult<rtio::SocketAddr> {
sockname(self.fd(), libc::getsockname)
}
}
@ -436,7 +445,7 @@ pub struct TcpListener {
}
impl TcpListener {
pub fn bind(addr: ip::SocketAddr) -> IoResult<TcpListener> {
pub fn bind(addr: rtio::SocketAddr) -> IoResult<TcpListener> {
let fd = try!(socket(addr, libc::SOCK_STREAM));
let ret = TcpListener { inner: Inner::new(fd) };
@ -477,7 +486,7 @@ impl rtio::RtioTcpListener for TcpListener {
}
impl rtio::RtioSocket for TcpListener {
fn socket_name(&mut self) -> IoResult<ip::SocketAddr> {
fn socket_name(&mut self) -> IoResult<rtio::SocketAddr> {
sockname(self.fd(), libc::getsockname)
}
}
@ -512,7 +521,7 @@ impl TcpAcceptor {
}
impl rtio::RtioSocket for TcpAcceptor {
fn socket_name(&mut self) -> IoResult<ip::SocketAddr> {
fn socket_name(&mut self) -> IoResult<rtio::SocketAddr> {
sockname(self.fd(), libc::getsockname)
}
}
@ -540,7 +549,7 @@ pub struct UdpSocket {
}
impl UdpSocket {
pub fn bind(addr: ip::SocketAddr) -> IoResult<UdpSocket> {
pub fn bind(addr: rtio::SocketAddr) -> IoResult<UdpSocket> {
let fd = try!(socket(addr, libc::SOCK_DGRAM));
let ret = UdpSocket {
inner: Arc::new(Inner::new(fd)),
@ -570,7 +579,7 @@ impl UdpSocket {
on as libc::c_int)
}
pub fn set_membership(&mut self, addr: ip::IpAddr,
pub fn set_membership(&mut self, addr: rtio::IpAddr,
opt: libc::c_int) -> IoResult<()> {
match ip_to_inaddr(addr) {
InAddr(addr) => {
@ -606,7 +615,7 @@ impl UdpSocket {
}
impl rtio::RtioSocket for UdpSocket {
fn socket_name(&mut self) -> IoResult<ip::SocketAddr> {
fn socket_name(&mut self) -> IoResult<rtio::SocketAddr> {
sockname(self.fd(), libc::getsockname)
}
}
@ -615,7 +624,7 @@ impl rtio::RtioSocket for UdpSocket {
#[cfg(unix)] type msglen_t = libc::size_t;
impl rtio::RtioUdpSocket for UdpSocket {
fn recvfrom(&mut self, buf: &mut [u8]) -> IoResult<(uint, ip::SocketAddr)> {
fn recvfrom(&mut self, buf: &mut [u8]) -> IoResult<(uint, rtio::SocketAddr)> {
let fd = self.fd();
let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
let storagep = &mut storage as *mut _ as *mut libc::sockaddr;
@ -638,7 +647,7 @@ impl rtio::RtioUdpSocket for UdpSocket {
})
}
fn sendto(&mut self, buf: &[u8], dst: ip::SocketAddr) -> IoResult<()> {
fn sendto(&mut self, buf: &[u8], dst: rtio::SocketAddr) -> IoResult<()> {
let (dst, dstlen) = addr_to_sockaddr(dst);
let dstp = &dst as *_ as *libc::sockaddr;
let dstlen = dstlen as libc::socklen_t;
@ -657,32 +666,28 @@ impl rtio::RtioUdpSocket for UdpSocket {
let n = try!(write(fd, self.write_deadline, buf, false, dolock, dowrite));
if n != buf.len() {
Err(io::IoError {
kind: io::ShortWrite(n),
desc: "couldn't send entire packet at once",
detail: None,
})
Err(util::short_write(n, "couldn't send entire packet at once"))
} else {
Ok(())
}
}
fn join_multicast(&mut self, multi: ip::IpAddr) -> IoResult<()> {
fn join_multicast(&mut self, multi: rtio::IpAddr) -> IoResult<()> {
match multi {
ip::Ipv4Addr(..) => {
rtio::Ipv4Addr(..) => {
self.set_membership(multi, libc::IP_ADD_MEMBERSHIP)
}
ip::Ipv6Addr(..) => {
rtio::Ipv6Addr(..) => {
self.set_membership(multi, libc::IPV6_ADD_MEMBERSHIP)
}
}
}
fn leave_multicast(&mut self, multi: ip::IpAddr) -> IoResult<()> {
fn leave_multicast(&mut self, multi: rtio::IpAddr) -> IoResult<()> {
match multi {
ip::Ipv4Addr(..) => {
rtio::Ipv4Addr(..) => {
self.set_membership(multi, libc::IP_DROP_MEMBERSHIP)
}
ip::Ipv6Addr(..) => {
rtio::Ipv6Addr(..) => {
self.set_membership(multi, libc::IPV6_DROP_MEMBERSHIP)
}
}
@ -821,7 +826,7 @@ pub fn read<T>(fd: sock_t,
}
match ret {
0 => Err(io::standard_error(io::EndOfFile)),
0 => Err(util::eof()),
n if n < 0 => Err(last_error()),
n => Ok(n as uint)
}
@ -858,13 +863,9 @@ pub fn write<T>(fd: sock_t,
// As with read(), first wait for the socket to be ready for
// the I/O operation.
match util::await(fd, deadline, util::Writable) {
Err(ref e) if e.kind == io::TimedOut && written > 0 => {
Err(ref e) if e.code == libc::EOF as uint && written > 0 => {
assert!(deadline.is_some());
return Err(io::IoError {
kind: io::ShortWrite(written),
desc: "short write",
detail: None,
})
return Err(util::short_write(written, "short write"))
}
Err(e) => return Err(e),
Ok(()) => {}

View File

@ -11,13 +11,12 @@
use alloc::arc::Arc;
use libc;
use std::c_str::CString;
use std::intrinsics;
use std::io;
use std::mem;
use std::rt::mutex;
use std::rt::rtio;
use std::unstable::mutex;
use std::rt::rtio::{IoResult, IoError};
use super::{IoResult, retry};
use super::retry;
use super::net;
use super::util;
use super::c;
@ -34,15 +33,17 @@ fn addr_to_sockaddr_un(addr: &CString) -> IoResult<(libc::sockaddr_storage, uint
// the sun_path length is limited to SUN_LEN (with null)
assert!(mem::size_of::<libc::sockaddr_storage>() >=
mem::size_of::<libc::sockaddr_un>());
let mut storage: libc::sockaddr_storage = unsafe { intrinsics::init() };
let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
let s: &mut libc::sockaddr_un = unsafe { mem::transmute(&mut storage) };
let len = addr.len();
if len > s.sun_path.len() - 1 {
return Err(io::IoError {
kind: io::InvalidInput,
desc: "path must be smaller than SUN_LEN",
detail: None,
#[cfg(unix)] use ERROR = libc::EINVAL;
#[cfg(windows)] use ERROR = libc::WSAEINVAL;
return Err(IoError {
code: ERROR as uint,
extra: 0,
detail: Some("path must be smaller than SUN_LEN".to_str()),
})
}
s.sun_family = libc::AF_UNIX as libc::sa_family_t;
@ -244,7 +245,7 @@ impl UnixAcceptor {
if self.deadline != 0 {
try!(util::await(self.fd(), Some(self.deadline), util::Readable));
}
let mut storage: libc::sockaddr_storage = unsafe { intrinsics::init() };
let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
let storagep = &mut storage as *mut libc::sockaddr_storage;
let size = mem::size_of::<libc::sockaddr_storage>();
let mut size = size as libc::socklen_t;

View File

@ -10,16 +10,13 @@
use libc::{pid_t, c_void, c_int};
use libc;
use std::io;
use std::mem;
use std::os;
use std::ptr;
use std::rt::rtio;
use std::rt::rtio::ProcessConfig;
use std::rt::rtio::{ProcessConfig, IoResult, IoError};
use std::c_str::CString;
use p = std::io::process;
use super::IoResult;
use super::file;
use super::util;
@ -48,7 +45,7 @@ pub struct Process {
handle: *(),
/// None until finish() is called.
exit_code: Option<p::ProcessExit>,
exit_code: Option<rtio::ProcessExit>,
/// Manually delivered signal
exit_signal: Option<int>,
@ -59,7 +56,7 @@ pub struct Process {
#[cfg(unix)]
enum Req {
NewChild(libc::pid_t, Sender<p::ProcessExit>, u64),
NewChild(libc::pid_t, Sender<rtio::ProcessExit>, u64),
}
impl Process {
@ -67,20 +64,21 @@ impl Process {
/// by the OS. Operations on this process will be blocking instead of using
/// the runtime for sleeping just this current task.
pub fn spawn(cfg: ProcessConfig)
-> Result<(Process, Vec<Option<file::FileDesc>>), io::IoError>
-> IoResult<(Process, Vec<Option<file::FileDesc>>)>
{
// right now we only handle stdin/stdout/stderr.
if cfg.extra_io.len() > 0 {
return Err(super::unimpl());
}
fn get_io(io: p::StdioContainer, ret: &mut Vec<Option<file::FileDesc>>)
fn get_io(io: rtio::StdioContainer,
ret: &mut Vec<Option<file::FileDesc>>)
-> (Option<os::Pipe>, c_int)
{
match io {
p::Ignored => { ret.push(None); (None, -1) }
p::InheritFd(fd) => { ret.push(None); (None, fd) }
p::CreatePipe(readable, _writable) => {
rtio::Ignored => { ret.push(None); (None, -1) }
rtio::InheritFd(fd) => { ret.push(None); (None, fd) }
rtio::CreatePipe(readable, _writable) => {
let pipe = os::pipe();
let (theirs, ours) = if readable {
(pipe.input, pipe.out)
@ -133,7 +131,7 @@ impl rtio::RtioProcess for Process {
self.deadline = timeout.map(|i| i + ::io::timer::now()).unwrap_or(0);
}
fn wait(&mut self) -> IoResult<p::ProcessExit> {
fn wait(&mut self) -> IoResult<rtio::ProcessExit> {
match self.exit_code {
Some(code) => Ok(code),
None => {
@ -143,7 +141,7 @@ impl rtio::RtioProcess for Process {
// consider it as having died via a signal.
let code = match self.exit_signal {
None => code,
Some(signal) if cfg!(windows) => p::ExitSignal(signal),
Some(signal) if cfg!(windows) => rtio::ExitSignal(signal),
Some(..) => code,
};
self.exit_code = Some(code);
@ -152,7 +150,10 @@ impl rtio::RtioProcess for Process {
}
}
fn kill(&mut self, signum: int) -> Result<(), io::IoError> {
fn kill(&mut self, signum: int) -> IoResult<()> {
#[cfg(unix)] use ERROR = libc::EINVAL;
#[cfg(windows)] use ERROR = libc::ERROR_NOTHING_TO_TERMINATE;
// On linux (and possibly other unices), a process that has exited will
// continue to accept signals because it is "defunct". The delivery of
// signals will only fail once the child has been reaped. For this
@ -169,10 +170,10 @@ impl rtio::RtioProcess for Process {
// and we kill it, then on unix we might ending up killing a
// newer process that happens to have the same (re-used) id
match self.exit_code {
Some(..) => return Err(io::IoError {
kind: io::OtherIoError,
desc: "can't kill an exited process",
detail: None,
Some(..) => return Err(IoError {
code: ERROR as uint,
extra: 0,
detail: Some("can't kill an exited process".to_str()),
}),
None => {}
}
@ -194,7 +195,7 @@ impl Drop for Process {
}
#[cfg(windows)]
unsafe fn killpid(pid: pid_t, signal: int) -> Result<(), io::IoError> {
unsafe fn killpid(pid: pid_t, signal: int) -> IoResult<()> {
let handle = libc::OpenProcess(libc::PROCESS_TERMINATE |
libc::PROCESS_QUERY_INFORMATION,
libc::FALSE, pid as libc::DWORD);
@ -233,7 +234,7 @@ unsafe fn killpid(pid: pid_t, signal: int) -> Result<(), io::IoError> {
}
#[cfg(not(windows))]
unsafe fn killpid(pid: pid_t, signal: int) -> Result<(), io::IoError> {
unsafe fn killpid(pid: pid_t, signal: int) -> IoResult<()> {
let r = libc::funcs::posix88::signal::kill(pid, signal as c_int);
super::mkerr_libc(r)
}
@ -521,12 +522,13 @@ fn spawn_process_os(cfg: ProcessConfig, in_fd: c_int, out_fd: c_int, err_fd: c_i
(bytes[1] << 16) as i32 |
(bytes[2] << 8) as i32 |
(bytes[3] << 0) as i32;
Err(io::IoError::from_errno(errno as uint, false))
Err(IoError {
code: errno as uint,
detail: None,
extra: 0,
})
}
Err(e) => {
assert!(e.kind == io::BrokenPipe ||
e.kind == io::EndOfFile,
"unexpected error: {}", e);
Err(..) => {
Ok(SpawnProcessResult {
pid: pid,
handle: ptr::null()
@ -757,7 +759,7 @@ fn free_handle(_handle: *()) {
}
#[cfg(unix)]
fn translate_status(status: c_int) -> p::ProcessExit {
fn translate_status(status: c_int) -> rtio::ProcessExit {
#![allow(non_snake_case_functions)]
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
@ -776,9 +778,9 @@ fn translate_status(status: c_int) -> p::ProcessExit {
}
if imp::WIFEXITED(status) {
p::ExitStatus(imp::WEXITSTATUS(status) as int)
rtio::ExitStatus(imp::WEXITSTATUS(status) as int)
} else {
p::ExitSignal(imp::WTERMSIG(status) as int)
rtio::ExitSignal(imp::WTERMSIG(status) as int)
}
}
@ -793,7 +795,7 @@ fn translate_status(status: c_int) -> p::ProcessExit {
* with the same id.
*/
#[cfg(windows)]
fn waitpid(pid: pid_t, deadline: u64) -> IoResult<p::ProcessExit> {
fn waitpid(pid: pid_t, deadline: u64) -> IoResult<rtio::ProcessExit> {
use libc::types::os::arch::extra::DWORD;
use libc::consts::os::extra::{
SYNCHRONIZE,
@ -828,7 +830,7 @@ fn waitpid(pid: pid_t, deadline: u64) -> IoResult<p::ProcessExit> {
}
if status != STILL_ACTIVE {
assert!(CloseHandle(process) != 0);
return Ok(p::ExitStatus(status as int));
return Ok(rtio::ExitStatus(status as int));
}
let interval = if deadline == 0 {
INFINITE
@ -853,7 +855,7 @@ fn waitpid(pid: pid_t, deadline: u64) -> IoResult<p::ProcessExit> {
}
#[cfg(unix)]
fn waitpid(pid: pid_t, deadline: u64) -> IoResult<p::ProcessExit> {
fn waitpid(pid: pid_t, deadline: u64) -> IoResult<rtio::ProcessExit> {
use std::cmp;
use std::comm;
@ -862,7 +864,7 @@ fn waitpid(pid: pid_t, deadline: u64) -> IoResult<p::ProcessExit> {
let mut status = 0 as c_int;
if deadline == 0 {
return match retry(|| unsafe { c::waitpid(pid, &mut status, 0) }) {
-1 => fail!("unknown waitpid error: {}", super::last_error()),
-1 => fail!("unknown waitpid error: {}", super::last_error().code),
_ => Ok(translate_status(status)),
}
}
@ -928,8 +930,8 @@ fn waitpid(pid: pid_t, deadline: u64) -> IoResult<p::ProcessExit> {
unsafe {
let mut pipes = [0, ..2];
assert_eq!(libc::pipe(pipes.as_mut_ptr()), 0);
util::set_nonblocking(pipes[0], true).unwrap();
util::set_nonblocking(pipes[1], true).unwrap();
util::set_nonblocking(pipes[0], true).ok().unwrap();
util::set_nonblocking(pipes[1], true).ok().unwrap();
WRITE_FD = pipes[1];
let mut old: c::sigaction = mem::zeroed();
@ -945,10 +947,10 @@ fn waitpid(pid: pid_t, deadline: u64) -> IoResult<p::ProcessExit> {
fn waitpid_helper(input: libc::c_int,
messages: Receiver<Req>,
(read_fd, old): (libc::c_int, c::sigaction)) {
util::set_nonblocking(input, true).unwrap();
util::set_nonblocking(input, true).ok().unwrap();
let mut set: c::fd_set = unsafe { mem::zeroed() };
let mut tv: libc::timeval;
let mut active = Vec::<(libc::pid_t, Sender<p::ProcessExit>, u64)>::new();
let mut active = Vec::<(libc::pid_t, Sender<rtio::ProcessExit>, u64)>::new();
let max = cmp::max(input, read_fd) + 1;
'outer: loop {
@ -1094,22 +1096,23 @@ fn waitpid(pid: pid_t, deadline: u64) -> IoResult<p::ProcessExit> {
}
}
fn waitpid_nowait(pid: pid_t) -> Option<p::ProcessExit> {
fn waitpid_nowait(pid: pid_t) -> Option<rtio::ProcessExit> {
return waitpid_os(pid);
// This code path isn't necessary on windows
#[cfg(windows)]
fn waitpid_os(_pid: pid_t) -> Option<p::ProcessExit> { None }
fn waitpid_os(_pid: pid_t) -> Option<rtio::ProcessExit> { None }
#[cfg(unix)]
fn waitpid_os(pid: pid_t) -> Option<p::ProcessExit> {
fn waitpid_os(pid: pid_t) -> Option<rtio::ProcessExit> {
let mut status = 0 as c_int;
match retry(|| unsafe {
c::waitpid(pid, &mut status, c::WNOHANG)
}) {
n if n == pid => Some(translate_status(status)),
0 => None,
n => fail!("unknown waitpid error `{}`: {}", n, super::last_error()),
n => fail!("unknown waitpid error `{}`: {}", n,
super::last_error().code),
}
}
}

View File

@ -51,10 +51,10 @@ use std::mem;
use std::os;
use std::ptr;
use std::rt::rtio;
use std::rt::rtio::IoResult;
use std::sync::atomics;
use std::comm;
use io::IoResult;
use io::c;
use io::file::FileDesc;
use io::helper_thread::Helper;
@ -67,7 +67,7 @@ pub struct Timer {
}
struct Inner {
tx: Option<Sender<()>>,
cb: Option<Box<rtio::Callback:Send>>,
interval: u64,
repeat: bool,
target: u64,
@ -119,13 +119,13 @@ fn helper(input: libc::c_int, messages: Receiver<Req>, _: ()) {
let mut timer = match active.shift() {
Some(timer) => timer, None => return
};
let tx = timer.tx.take_unwrap();
if tx.send_opt(()).is_ok() && timer.repeat {
timer.tx = Some(tx);
let mut cb = timer.cb.take_unwrap();
cb.call();
if timer.repeat {
timer.cb = Some(cb);
timer.target += timer.interval;
insert(timer, active);
} else {
drop(tx);
dead.push((timer.id, timer));
}
}
@ -190,7 +190,7 @@ fn helper(input: libc::c_int, messages: Receiver<Req>, _: ()) {
// drain the file descriptor
let mut buf = [0];
assert_eq!(fd.inner_read(buf).unwrap(), 1);
assert_eq!(fd.inner_read(buf).ok().unwrap(), 1);
}
-1 if os::errno() == libc::EINTR as int => {}
@ -209,7 +209,7 @@ impl Timer {
Ok(Timer {
id: id,
inner: Some(box Inner {
tx: None,
cb: None,
interval: 0,
target: 0,
repeat: false,
@ -245,38 +245,34 @@ impl Timer {
impl rtio::RtioTimer for Timer {
fn sleep(&mut self, msecs: u64) {
let mut inner = self.inner();
inner.tx = None; // cancel any previous request
inner.cb = None; // cancel any previous request
self.inner = Some(inner);
Timer::sleep(msecs);
}
fn oneshot(&mut self, msecs: u64) -> Receiver<()> {
fn oneshot(&mut self, msecs: u64, cb: Box<rtio::Callback:Send>) {
let now = now();
let mut inner = self.inner();
let (tx, rx) = channel();
inner.repeat = false;
inner.tx = Some(tx);
inner.cb = Some(cb);
inner.interval = msecs;
inner.target = now + msecs;
unsafe { HELPER.send(NewTimer(inner)); }
return rx;
}
fn period(&mut self, msecs: u64) -> Receiver<()> {
fn period(&mut self, msecs: u64, cb: Box<rtio::Callback:Send>) {
let now = now();
let mut inner = self.inner();
let (tx, rx) = channel();
inner.repeat = true;
inner.tx = Some(tx);
inner.cb = Some(cb);
inner.interval = msecs;
inner.target = now + msecs;
unsafe { HELPER.send(NewTimer(inner)); }
return rx;
}
}

View File

@ -9,11 +9,10 @@
// except according to those terms.
use libc;
use std::io::IoResult;
use std::io;
use std::mem;
use std::os;
use std::ptr;
use std::rt::rtio::{IoResult, IoError};
use super::c;
use super::net;
@ -25,10 +24,30 @@ pub enum SocketStatus {
Writable,
}
pub fn timeout(desc: &'static str) -> io::IoError {
io::IoError {
kind: io::TimedOut,
desc: desc,
pub fn timeout(desc: &'static str) -> IoError {
#[cfg(unix)] use ERROR = libc::ETIMEDOUT;
#[cfg(windows)] use ERROR = libc::ERROR_OPERATION_ABORTED;
IoError {
code: ERROR as uint,
extra: 0,
detail: Some(desc.to_str()),
}
}
pub fn short_write(n: uint, desc: &'static str) -> IoError {
#[cfg(unix)] use ERROR = libc::EAGAIN;
#[cfg(windows)] use ERROR = libc::ERROR_OPERATION_ABORTED;
IoError {
code: ERROR as uint,
extra: n,
detail: Some(desc.to_str()),
}
}
pub fn eof() -> IoError {
IoError {
code: libc::EOF as uint,
extra: 0,
detail: None,
}
}
@ -100,7 +119,11 @@ pub fn connect_timeout(fd: net::sock_t,
if err == 0 {
Ok(())
} else {
Err(io::IoError::from_errno(err as uint, true))
Err(IoError {
code: err as uint,
extra: 0,
detail: Some(os::error_string(err as uint)),
})
}
}
}

View File

@ -17,15 +17,13 @@
use std::any::Any;
use std::mem;
use std::rt::bookkeeping;
use std::rt::env;
use std::rt::local::Local;
use std::rt::mutex::NativeMutex;
use std::rt::rtio;
use std::rt::stack;
use std::rt::task::{Task, BlockedTask, SendMessage};
use std::rt::task::{Task, BlockedTask, TaskOpts};
use std::rt::thread::Thread;
use std::rt;
use std::task::TaskOpts;
use std::unstable::mutex::NativeMutex;
use io;
use task;
@ -51,27 +49,19 @@ fn ops() -> Box<Ops> {
/// Spawns a function with the default configuration
pub fn spawn(f: proc():Send) {
spawn_opts(TaskOpts::new(), f)
spawn_opts(TaskOpts { name: None, stack_size: None, on_exit: None }, f)
}
/// Spawns a new task given the configuration options and a procedure to run
/// inside the task.
pub fn spawn_opts(opts: TaskOpts, f: proc():Send) {
let TaskOpts {
notify_chan, name, stack_size,
stderr, stdout,
} = opts;
let TaskOpts { name, stack_size, on_exit } = opts;
let mut task = box Task::new();
task.name = name;
task.stderr = stderr;
task.stdout = stdout;
match notify_chan {
Some(chan) => { task.death.on_exit = Some(SendMessage(chan)); }
None => {}
}
task.death.on_exit = on_exit;
let stack = stack_size.unwrap_or(env::min_stack());
let stack = stack_size.unwrap_or(rt::min_stack());
let task = task;
let ops = ops();
@ -267,9 +257,8 @@ impl rt::Runtime for Ops {
#[cfg(test)]
mod tests {
use std::rt::local::Local;
use std::rt::task::Task;
use std::rt::task::{Task, TaskOpts};
use std::task;
use std::task::TaskOpts;
use super::{spawn, spawn_opts, Ops};
#[test]
@ -297,7 +286,7 @@ mod tests {
opts.name = Some("test".into_maybe_owned());
opts.stack_size = Some(20 * 4096);
let (tx, rx) = channel();
opts.notify_chan = Some(tx);
opts.on_exit = Some(proc(r) tx.send(r));
spawn_opts(opts, proc() {});
assert!(rx.recv().is_ok());
}
@ -306,7 +295,7 @@ mod tests {
fn smoke_opts_fail() {
let mut opts = TaskOpts::new();
let (tx, rx) = channel();
opts.notify_chan = Some(tx);
opts.on_exit = Some(proc(r) tx.send(r));
spawn_opts(opts, proc() { fail!() });
assert!(rx.recv().is_err());
}