1
Fork 0

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -10,16 +10,13 @@
use libc::{pid_t, c_void, c_int}; use libc::{pid_t, c_void, c_int};
use libc; use libc;
use std::io;
use std::mem; use std::mem;
use std::os; use std::os;
use std::ptr; use std::ptr;
use std::rt::rtio; use std::rt::rtio;
use std::rt::rtio::ProcessConfig; use std::rt::rtio::{ProcessConfig, IoResult, IoError};
use std::c_str::CString; use std::c_str::CString;
use p = std::io::process;
use super::IoResult;
use super::file; use super::file;
use super::util; use super::util;
@ -48,7 +45,7 @@ pub struct Process {
handle: *(), handle: *(),
/// None until finish() is called. /// None until finish() is called.
exit_code: Option<p::ProcessExit>, exit_code: Option<rtio::ProcessExit>,
/// Manually delivered signal /// Manually delivered signal
exit_signal: Option<int>, exit_signal: Option<int>,
@ -59,7 +56,7 @@ pub struct Process {
#[cfg(unix)] #[cfg(unix)]
enum Req { enum Req {
NewChild(libc::pid_t, Sender<p::ProcessExit>, u64), NewChild(libc::pid_t, Sender<rtio::ProcessExit>, u64),
} }
impl Process { impl Process {
@ -67,20 +64,21 @@ impl Process {
/// by the OS. Operations on this process will be blocking instead of using /// by the OS. Operations on this process will be blocking instead of using
/// the runtime for sleeping just this current task. /// the runtime for sleeping just this current task.
pub fn spawn(cfg: ProcessConfig) 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. // right now we only handle stdin/stdout/stderr.
if cfg.extra_io.len() > 0 { if cfg.extra_io.len() > 0 {
return Err(super::unimpl()); 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) -> (Option<os::Pipe>, c_int)
{ {
match io { match io {
p::Ignored => { ret.push(None); (None, -1) } rtio::Ignored => { ret.push(None); (None, -1) }
p::InheritFd(fd) => { ret.push(None); (None, fd) } rtio::InheritFd(fd) => { ret.push(None); (None, fd) }
p::CreatePipe(readable, _writable) => { rtio::CreatePipe(readable, _writable) => {
let pipe = os::pipe(); let pipe = os::pipe();
let (theirs, ours) = if readable { let (theirs, ours) = if readable {
(pipe.input, pipe.out) (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); 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 { match self.exit_code {
Some(code) => Ok(code), Some(code) => Ok(code),
None => { None => {
@ -143,7 +141,7 @@ impl rtio::RtioProcess for Process {
// consider it as having died via a signal. // consider it as having died via a signal.
let code = match self.exit_signal { let code = match self.exit_signal {
None => code, None => code,
Some(signal) if cfg!(windows) => p::ExitSignal(signal), Some(signal) if cfg!(windows) => rtio::ExitSignal(signal),
Some(..) => code, Some(..) => code,
}; };
self.exit_code = 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 // On linux (and possibly other unices), a process that has exited will
// continue to accept signals because it is "defunct". The delivery of // continue to accept signals because it is "defunct". The delivery of
// signals will only fail once the child has been reaped. For this // 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 // and we kill it, then on unix we might ending up killing a
// newer process that happens to have the same (re-used) id // newer process that happens to have the same (re-used) id
match self.exit_code { match self.exit_code {
Some(..) => return Err(io::IoError { Some(..) => return Err(IoError {
kind: io::OtherIoError, code: ERROR as uint,
desc: "can't kill an exited process", extra: 0,
detail: None, detail: Some("can't kill an exited process".to_str()),
}), }),
None => {} None => {}
} }
@ -194,7 +195,7 @@ impl Drop for Process {
} }
#[cfg(windows)] #[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 | let handle = libc::OpenProcess(libc::PROCESS_TERMINATE |
libc::PROCESS_QUERY_INFORMATION, libc::PROCESS_QUERY_INFORMATION,
libc::FALSE, pid as libc::DWORD); libc::FALSE, pid as libc::DWORD);
@ -233,7 +234,7 @@ unsafe fn killpid(pid: pid_t, signal: int) -> Result<(), io::IoError> {
} }
#[cfg(not(windows))] #[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); let r = libc::funcs::posix88::signal::kill(pid, signal as c_int);
super::mkerr_libc(r) 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[1] << 16) as i32 |
(bytes[2] << 8) as i32 | (bytes[2] << 8) as i32 |
(bytes[3] << 0) 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) => { Err(..) => {
assert!(e.kind == io::BrokenPipe ||
e.kind == io::EndOfFile,
"unexpected error: {}", e);
Ok(SpawnProcessResult { Ok(SpawnProcessResult {
pid: pid, pid: pid,
handle: ptr::null() handle: ptr::null()
@ -757,7 +759,7 @@ fn free_handle(_handle: *()) {
} }
#[cfg(unix)] #[cfg(unix)]
fn translate_status(status: c_int) -> p::ProcessExit { fn translate_status(status: c_int) -> rtio::ProcessExit {
#![allow(non_snake_case_functions)] #![allow(non_snake_case_functions)]
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
#[cfg(target_os = "android")] #[cfg(target_os = "android")]
@ -776,9 +778,9 @@ fn translate_status(status: c_int) -> p::ProcessExit {
} }
if imp::WIFEXITED(status) { if imp::WIFEXITED(status) {
p::ExitStatus(imp::WEXITSTATUS(status) as int) rtio::ExitStatus(imp::WEXITSTATUS(status) as int)
} else { } 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. * with the same id.
*/ */
#[cfg(windows)] #[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::types::os::arch::extra::DWORD;
use libc::consts::os::extra::{ use libc::consts::os::extra::{
SYNCHRONIZE, SYNCHRONIZE,
@ -828,7 +830,7 @@ fn waitpid(pid: pid_t, deadline: u64) -> IoResult<p::ProcessExit> {
} }
if status != STILL_ACTIVE { if status != STILL_ACTIVE {
assert!(CloseHandle(process) != 0); assert!(CloseHandle(process) != 0);
return Ok(p::ExitStatus(status as int)); return Ok(rtio::ExitStatus(status as int));
} }
let interval = if deadline == 0 { let interval = if deadline == 0 {
INFINITE INFINITE
@ -853,7 +855,7 @@ fn waitpid(pid: pid_t, deadline: u64) -> IoResult<p::ProcessExit> {
} }
#[cfg(unix)] #[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::cmp;
use std::comm; use std::comm;
@ -862,7 +864,7 @@ fn waitpid(pid: pid_t, deadline: u64) -> IoResult<p::ProcessExit> {
let mut status = 0 as c_int; let mut status = 0 as c_int;
if deadline == 0 { if deadline == 0 {
return match retry(|| unsafe { c::waitpid(pid, &mut status, 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)), _ => Ok(translate_status(status)),
} }
} }
@ -928,8 +930,8 @@ fn waitpid(pid: pid_t, deadline: u64) -> IoResult<p::ProcessExit> {
unsafe { unsafe {
let mut pipes = [0, ..2]; let mut pipes = [0, ..2];
assert_eq!(libc::pipe(pipes.as_mut_ptr()), 0); assert_eq!(libc::pipe(pipes.as_mut_ptr()), 0);
util::set_nonblocking(pipes[0], true).unwrap(); util::set_nonblocking(pipes[0], true).ok().unwrap();
util::set_nonblocking(pipes[1], true).unwrap(); util::set_nonblocking(pipes[1], true).ok().unwrap();
WRITE_FD = pipes[1]; WRITE_FD = pipes[1];
let mut old: c::sigaction = mem::zeroed(); 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, fn waitpid_helper(input: libc::c_int,
messages: Receiver<Req>, messages: Receiver<Req>,
(read_fd, old): (libc::c_int, c::sigaction)) { (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 set: c::fd_set = unsafe { mem::zeroed() };
let mut tv: libc::timeval; 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; let max = cmp::max(input, read_fd) + 1;
'outer: loop { '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); return waitpid_os(pid);
// This code path isn't necessary on windows // This code path isn't necessary on windows
#[cfg(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)] #[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; let mut status = 0 as c_int;
match retry(|| unsafe { match retry(|| unsafe {
c::waitpid(pid, &mut status, c::WNOHANG) c::waitpid(pid, &mut status, c::WNOHANG)
}) { }) {
n if n == pid => Some(translate_status(status)), n if n == pid => Some(translate_status(status)),
0 => None, 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::os;
use std::ptr; use std::ptr;
use std::rt::rtio; use std::rt::rtio;
use std::rt::rtio::IoResult;
use std::sync::atomics; use std::sync::atomics;
use std::comm; use std::comm;
use io::IoResult;
use io::c; use io::c;
use io::file::FileDesc; use io::file::FileDesc;
use io::helper_thread::Helper; use io::helper_thread::Helper;
@ -67,7 +67,7 @@ pub struct Timer {
} }
struct Inner { struct Inner {
tx: Option<Sender<()>>, cb: Option<Box<rtio::Callback:Send>>,
interval: u64, interval: u64,
repeat: bool, repeat: bool,
target: u64, target: u64,
@ -119,13 +119,13 @@ fn helper(input: libc::c_int, messages: Receiver<Req>, _: ()) {
let mut timer = match active.shift() { let mut timer = match active.shift() {
Some(timer) => timer, None => return Some(timer) => timer, None => return
}; };
let tx = timer.tx.take_unwrap(); let mut cb = timer.cb.take_unwrap();
if tx.send_opt(()).is_ok() && timer.repeat { cb.call();
timer.tx = Some(tx); if timer.repeat {
timer.cb = Some(cb);
timer.target += timer.interval; timer.target += timer.interval;
insert(timer, active); insert(timer, active);
} else { } else {
drop(tx);
dead.push((timer.id, timer)); dead.push((timer.id, timer));
} }
} }
@ -190,7 +190,7 @@ fn helper(input: libc::c_int, messages: Receiver<Req>, _: ()) {
// drain the file descriptor // drain the file descriptor
let mut buf = [0]; 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 => {} -1 if os::errno() == libc::EINTR as int => {}
@ -209,7 +209,7 @@ impl Timer {
Ok(Timer { Ok(Timer {
id: id, id: id,
inner: Some(box Inner { inner: Some(box Inner {
tx: None, cb: None,
interval: 0, interval: 0,
target: 0, target: 0,
repeat: false, repeat: false,
@ -245,38 +245,34 @@ impl Timer {
impl rtio::RtioTimer for Timer { impl rtio::RtioTimer for Timer {
fn sleep(&mut self, msecs: u64) { fn sleep(&mut self, msecs: u64) {
let mut inner = self.inner(); let mut inner = self.inner();
inner.tx = None; // cancel any previous request inner.cb = None; // cancel any previous request
self.inner = Some(inner); self.inner = Some(inner);
Timer::sleep(msecs); 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 now = now();
let mut inner = self.inner(); let mut inner = self.inner();
let (tx, rx) = channel();
inner.repeat = false; inner.repeat = false;
inner.tx = Some(tx); inner.cb = Some(cb);
inner.interval = msecs; inner.interval = msecs;
inner.target = now + msecs; inner.target = now + msecs;
unsafe { HELPER.send(NewTimer(inner)); } 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 now = now();
let mut inner = self.inner(); let mut inner = self.inner();
let (tx, rx) = channel();
inner.repeat = true; inner.repeat = true;
inner.tx = Some(tx); inner.cb = Some(cb);
inner.interval = msecs; inner.interval = msecs;
inner.target = now + msecs; inner.target = now + msecs;
unsafe { HELPER.send(NewTimer(inner)); } unsafe { HELPER.send(NewTimer(inner)); }
return rx;
} }
} }

View file

@ -9,11 +9,10 @@
// except according to those terms. // except according to those terms.
use libc; use libc;
use std::io::IoResult;
use std::io;
use std::mem; use std::mem;
use std::os; use std::os;
use std::ptr; use std::ptr;
use std::rt::rtio::{IoResult, IoError};
use super::c; use super::c;
use super::net; use super::net;
@ -25,10 +24,30 @@ pub enum SocketStatus {
Writable, Writable,
} }
pub fn timeout(desc: &'static str) -> io::IoError { pub fn timeout(desc: &'static str) -> IoError {
io::IoError { #[cfg(unix)] use ERROR = libc::ETIMEDOUT;
kind: io::TimedOut, #[cfg(windows)] use ERROR = libc::ERROR_OPERATION_ABORTED;
desc: desc, 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, detail: None,
} }
} }
@ -100,7 +119,11 @@ pub fn connect_timeout(fd: net::sock_t,
if err == 0 { if err == 0 {
Ok(()) Ok(())
} else { } 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::any::Any;
use std::mem; use std::mem;
use std::rt::bookkeeping; use std::rt::bookkeeping;
use std::rt::env;
use std::rt::local::Local; use std::rt::local::Local;
use std::rt::mutex::NativeMutex;
use std::rt::rtio; use std::rt::rtio;
use std::rt::stack; 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::thread::Thread;
use std::rt; use std::rt;
use std::task::TaskOpts;
use std::unstable::mutex::NativeMutex;
use io; use io;
use task; use task;
@ -51,27 +49,19 @@ fn ops() -> Box<Ops> {
/// Spawns a function with the default configuration /// Spawns a function with the default configuration
pub fn spawn(f: proc():Send) { 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 /// Spawns a new task given the configuration options and a procedure to run
/// inside the task. /// inside the task.
pub fn spawn_opts(opts: TaskOpts, f: proc():Send) { pub fn spawn_opts(opts: TaskOpts, f: proc():Send) {
let TaskOpts { let TaskOpts { name, stack_size, on_exit } = opts;
notify_chan, name, stack_size,
stderr, stdout,
} = opts;
let mut task = box Task::new(); let mut task = box Task::new();
task.name = name; task.name = name;
task.stderr = stderr; task.death.on_exit = on_exit;
task.stdout = stdout;
match notify_chan {
Some(chan) => { task.death.on_exit = Some(SendMessage(chan)); }
None => {}
}
let stack = stack_size.unwrap_or(env::min_stack()); let stack = stack_size.unwrap_or(rt::min_stack());
let task = task; let task = task;
let ops = ops(); let ops = ops();
@ -267,9 +257,8 @@ impl rt::Runtime for Ops {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::rt::local::Local; use std::rt::local::Local;
use std::rt::task::Task; use std::rt::task::{Task, TaskOpts};
use std::task; use std::task;
use std::task::TaskOpts;
use super::{spawn, spawn_opts, Ops}; use super::{spawn, spawn_opts, Ops};
#[test] #[test]
@ -297,7 +286,7 @@ mod tests {
opts.name = Some("test".into_maybe_owned()); opts.name = Some("test".into_maybe_owned());
opts.stack_size = Some(20 * 4096); opts.stack_size = Some(20 * 4096);
let (tx, rx) = channel(); let (tx, rx) = channel();
opts.notify_chan = Some(tx); opts.on_exit = Some(proc(r) tx.send(r));
spawn_opts(opts, proc() {}); spawn_opts(opts, proc() {});
assert!(rx.recv().is_ok()); assert!(rx.recv().is_ok());
} }
@ -306,7 +295,7 @@ mod tests {
fn smoke_opts_fail() { fn smoke_opts_fail() {
let mut opts = TaskOpts::new(); let mut opts = TaskOpts::new();
let (tx, rx) = channel(); let (tx, rx) = channel();
opts.notify_chan = Some(tx); opts.on_exit = Some(proc(r) tx.send(r));
spawn_opts(opts, proc() { fail!() }); spawn_opts(opts, proc() { fail!() });
assert!(rx.recv().is_err()); assert!(rx.recv().is_err());
} }