Another round of test fixes and merge conflicts
This commit is contained in:
parent
d425218395
commit
188e471339
|
@ -145,7 +145,7 @@ fn decode_inner(s: &str, full_url: bool) -> ~str {
|
|||
let mut bytes = [0, 0];
|
||||
match rdr.read(bytes) {
|
||||
Some(2) => {}
|
||||
_ => fail2!() // XXX: malformed url?
|
||||
_ => fail!() // XXX: malformed url?
|
||||
}
|
||||
let ch = uint::parse_bytes(bytes, 16u).unwrap() as u8 as char;
|
||||
|
||||
|
@ -279,7 +279,7 @@ pub fn decode_form_urlencoded(s: &[u8]) -> HashMap<~str, ~[~str]> {
|
|||
let mut bytes = [0, 0];
|
||||
match rdr.read(bytes) {
|
||||
Some(2) => {}
|
||||
_ => fail2!() // XXX: malformed?
|
||||
_ => fail!() // XXX: malformed?
|
||||
}
|
||||
uint::parse_bytes(bytes, 16u).unwrap() as u8 as char
|
||||
}
|
||||
|
|
|
@ -11,7 +11,10 @@
|
|||
// rustpkg unit tests
|
||||
|
||||
use context::{BuildContext, Context, RustcFlags};
|
||||
use std::{io, os, run, str, task};
|
||||
use std::{os, run, str, task};
|
||||
use std::rt::io;
|
||||
use std::rt::io::Writer;
|
||||
use std::rt::io::file::FileInfo;
|
||||
use extra::arc::Arc;
|
||||
use extra::arc::RWArc;
|
||||
use extra::tempfile::TempDir;
|
||||
|
@ -81,8 +84,9 @@ fn git_repo_pkg_with_tag(a_tag: ~str) -> PkgId {
|
|||
}
|
||||
|
||||
fn writeFile(file_path: &Path, contents: &str) {
|
||||
let out = io::file_writer(file_path, [io::Create, io::Truncate]).unwrap();
|
||||
out.write_line(contents);
|
||||
let mut out = file_path.open_writer(io::CreateOrTruncate);
|
||||
out.write(contents.as_bytes());
|
||||
out.write(['\n' as u8]);
|
||||
}
|
||||
|
||||
fn mk_emptier_workspace(tag: &str) -> TempDir {
|
||||
|
@ -550,10 +554,11 @@ fn frob_source_file(workspace: &Path, pkgid: &PkgId, filename: &str) {
|
|||
debug!("Frobbed? {:?}", maybe_p);
|
||||
match maybe_p {
|
||||
Some(ref p) => {
|
||||
let w = io::file_writer(p, &[io::Append]);
|
||||
match w {
|
||||
Err(s) => { let _ = cond.raise((p.clone(), format!("Bad path: {}", s))); }
|
||||
Ok(w) => w.write_line("/* hi */")
|
||||
do io::io_error::cond.trap(|e| {
|
||||
cond.raise((p.clone(), format!("Bad path: {}", e.desc)));
|
||||
}).inside {
|
||||
let mut w = p.open_writer(io::Append);
|
||||
w.write(bytes!("/* hi */\n"));
|
||||
}
|
||||
}
|
||||
None => fail!("frob_source_file failed to find a source file in {}",
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
extern mod rustpkg;
|
||||
extern mod rustc;
|
||||
|
||||
use std::{io, os, task};
|
||||
use std::{os, task};
|
||||
use rustpkg::api;
|
||||
use rustpkg::version::NoVersion;
|
||||
use rustpkg::workcache_support::digest_file_with_date;
|
||||
|
@ -36,7 +36,7 @@ pub fn main() {
|
|||
}
|
||||
|
||||
if args[2] != ~"install" {
|
||||
io::println(format!("Warning: I don't know how to {}", args[2]));
|
||||
println(format!("Warning: I don't know how to {}", args[2]));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,10 @@
|
|||
extern mod rustpkg;
|
||||
extern mod rustc;
|
||||
|
||||
use std::{io, os};
|
||||
use std::os;
|
||||
use std::rt::io;
|
||||
use std::rt::io::Writer;
|
||||
use std::rt::io::file::FileInfo;
|
||||
use rustpkg::api;
|
||||
use rustpkg::version::NoVersion;
|
||||
|
||||
|
@ -42,9 +45,9 @@ pub fn main() {
|
|||
let out_path = os::self_exe_path().expect("Couldn't get self_exe path");
|
||||
|
||||
debug!("Writing file");
|
||||
let file = io::file_writer(&out_path.join("generated.rs"), [io::Create]).unwrap();
|
||||
file.write_str("pub fn wheeeee() { let xs = [1, 2, 3]; \
|
||||
for _ in xs.iter() { assert!(true); } }");
|
||||
let mut file = out_path.join("generated.rs").open_writer(io::Create);
|
||||
file.write("pub fn wheeeee() { let xs = [1, 2, 3]; \
|
||||
for _ in xs.iter() { assert!(true); } }".as_bytes());
|
||||
|
||||
let context = api::default_context(sysroot, api::default_workspace());
|
||||
api::install_pkg(&context, os::getcwd(), ~"fancy-lib", NoVersion, ~[]);
|
||||
|
|
|
@ -147,6 +147,7 @@ impl Listener {
|
|||
mod test {
|
||||
use libc;
|
||||
use rt::io::timer;
|
||||
use rt::io;
|
||||
use super::*;
|
||||
|
||||
// kill is only available on Unixes
|
||||
|
@ -158,7 +159,7 @@ mod test {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test] #[cfg(unix)]
|
||||
fn test_io_signal_smoketest() {
|
||||
let mut signal = Listener::new();
|
||||
signal.register(Interrupt);
|
||||
|
@ -166,11 +167,11 @@ mod test {
|
|||
timer::sleep(10);
|
||||
match signal.port.recv() {
|
||||
Interrupt => (),
|
||||
s => fail2!("Expected Interrupt, got {:?}", s),
|
||||
s => fail!("Expected Interrupt, got {:?}", s),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test] #[cfg(unix)]
|
||||
fn test_io_signal_two_signal_one_signum() {
|
||||
let mut s1 = Listener::new();
|
||||
let mut s2 = Listener::new();
|
||||
|
@ -180,15 +181,15 @@ mod test {
|
|||
timer::sleep(10);
|
||||
match s1.port.recv() {
|
||||
Interrupt => (),
|
||||
s => fail2!("Expected Interrupt, got {:?}", s),
|
||||
s => fail!("Expected Interrupt, got {:?}", s),
|
||||
}
|
||||
match s1.port.recv() {
|
||||
Interrupt => (),
|
||||
s => fail2!("Expected Interrupt, got {:?}", s),
|
||||
s => fail!("Expected Interrupt, got {:?}", s),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test] #[cfg(unix)]
|
||||
fn test_io_signal_unregister() {
|
||||
let mut s1 = Listener::new();
|
||||
let mut s2 = Listener::new();
|
||||
|
@ -198,7 +199,7 @@ mod test {
|
|||
sigint();
|
||||
timer::sleep(10);
|
||||
if s2.port.peek() {
|
||||
fail2!("Unexpected {:?}", s2.port.recv());
|
||||
fail!("Unexpected {:?}", s2.port.recv());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -206,8 +207,14 @@ mod test {
|
|||
#[test]
|
||||
fn test_io_signal_invalid_signum() {
|
||||
let mut s = Listener::new();
|
||||
if s.register(User1) {
|
||||
fail2!("Unexpected successful registry of signum {:?}", User1);
|
||||
let mut called = false;
|
||||
do io::io_error::cond.trap(|_| {
|
||||
called = true;
|
||||
}).inside {
|
||||
if s.register(User1) {
|
||||
fail!("Unexpected successful registry of signum {:?}", User1);
|
||||
}
|
||||
}
|
||||
assert!(called);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,20 +30,57 @@ use fmt;
|
|||
use libc;
|
||||
use option::{Option, Some, None};
|
||||
use result::{Ok, Err};
|
||||
use rt::rtio::{IoFactory, RtioTTY, with_local_io, RtioPipe};
|
||||
use super::{Reader, Writer, io_error};
|
||||
use rt::rtio::{IoFactory, RtioTTY, RtioFileStream, with_local_io,
|
||||
CloseAsynchronously};
|
||||
use super::{Reader, Writer, io_error, IoError, OtherIoError};
|
||||
|
||||
// And so begins the tale of acquiring a uv handle to a stdio stream on all
|
||||
// platforms in all situations. Our story begins by splitting the world into two
|
||||
// categories, windows and unix. Then one day the creators of unix said let
|
||||
// there be redirection! And henceforth there was redirection away from the
|
||||
// console for standard I/O streams.
|
||||
//
|
||||
// After this day, the world split into four factions:
|
||||
//
|
||||
// 1. Unix with stdout on a terminal.
|
||||
// 2. Unix with stdout redirected.
|
||||
// 3. Windows with stdout on a terminal.
|
||||
// 4. Windows with stdout redirected.
|
||||
//
|
||||
// Many years passed, and then one day the nation of libuv decided to unify this
|
||||
// world. After months of toiling, uv created three ideas: TTY, Pipe, File.
|
||||
// These three ideas propagated throughout the lands and the four great factions
|
||||
// decided to settle among them.
|
||||
//
|
||||
// The groups of 1, 2, and 3 all worked very hard towards the idea of TTY. Upon
|
||||
// doing so, they even enhanced themselves further then their Pipe/File
|
||||
// brethren, becoming the dominant powers.
|
||||
//
|
||||
// The group of 4, however, decided to work independently. They abandoned the
|
||||
// common TTY belief throughout, and even abandoned the fledgling Pipe belief.
|
||||
// The members of the 4th faction decided to only align themselves with File.
|
||||
//
|
||||
// tl;dr; TTY works on everything but when windows stdout is redirected, in that
|
||||
// case pipe also doesn't work, but magically file does!
|
||||
enum StdSource {
|
||||
TTY(~RtioTTY),
|
||||
File(~RtioFileStream),
|
||||
}
|
||||
|
||||
#[fixed_stack_segment] #[inline(never)]
|
||||
fn tty<T>(fd: libc::c_int, f: &fn(~RtioTTY) -> T) -> T {
|
||||
fn src<T>(fd: libc::c_int, readable: bool, f: &fn(StdSource) -> T) -> T {
|
||||
do with_local_io |io| {
|
||||
// Always pass in readable as true, otherwise libuv turns our writes
|
||||
// into blocking writes. We also need to dup the file descriptor because
|
||||
// the tty will be closed when it's dropped.
|
||||
match io.tty_open(unsafe { libc::dup(fd) }, true) {
|
||||
Ok(tty) => Some(f(tty)),
|
||||
Err(e) => {
|
||||
io_error::cond.raise(e);
|
||||
None
|
||||
let fd = unsafe { libc::dup(fd) };
|
||||
match io.tty_open(fd, readable) {
|
||||
Ok(tty) => Some(f(TTY(tty))),
|
||||
Err(_) => {
|
||||
// It's not really that desirable if these handles are closed
|
||||
// synchronously, and because they're squirreled away in a task
|
||||
// structure the destructors will be run when the task is
|
||||
// attempted to get destroyed. This means that if we run a
|
||||
// synchronous destructor we'll attempt to do some scheduling
|
||||
// operations which will just result in sadness.
|
||||
Some(f(File(io.fs_from_raw_fd(fd, CloseAsynchronously))))
|
||||
}
|
||||
}
|
||||
}.unwrap()
|
||||
|
@ -54,15 +91,7 @@ fn tty<T>(fd: libc::c_int, f: &fn(~RtioTTY) -> T) -> T {
|
|||
/// See `stdout()` for notes about this function.
|
||||
#[fixed_stack_segment] #[inline(never)]
|
||||
pub fn stdin() -> StdReader {
|
||||
do with_local_io |io| {
|
||||
match io.pipe_open(unsafe { libc::dup(libc::STDIN_FILENO) }) {
|
||||
Ok(stream) => Some(StdReader { inner: stream }),
|
||||
Err(e) => {
|
||||
io_error::cond.raise(e);
|
||||
None
|
||||
}
|
||||
}
|
||||
}.unwrap()
|
||||
do src(libc::STDIN_FILENO, true) |src| { StdReader { inner: src } }
|
||||
}
|
||||
|
||||
/// Creates a new non-blocking handle to the stdout of the current process.
|
||||
|
@ -72,14 +101,14 @@ pub fn stdin() -> StdReader {
|
|||
/// task context because the stream returned will be a non-blocking object using
|
||||
/// the local scheduler to perform the I/O.
|
||||
pub fn stdout() -> StdWriter {
|
||||
do tty(libc::STDOUT_FILENO) |tty| { StdWriter { inner: tty } }
|
||||
do src(libc::STDOUT_FILENO, false) |src| { StdWriter { inner: src } }
|
||||
}
|
||||
|
||||
/// Creates a new non-blocking handle to the stderr of the current process.
|
||||
///
|
||||
/// See `stdout()` for notes about this function.
|
||||
pub fn stderr() -> StdWriter {
|
||||
do tty(libc::STDERR_FILENO) |tty| { StdWriter { inner: tty } }
|
||||
do src(libc::STDERR_FILENO, false) |src| { StdWriter { inner: src } }
|
||||
}
|
||||
|
||||
/// Prints a string to the stdout of the current process. No newline is emitted
|
||||
|
@ -117,12 +146,16 @@ pub fn println_args(fmt: &fmt::Arguments) {
|
|||
|
||||
/// Representation of a reader of a standard input stream
|
||||
pub struct StdReader {
|
||||
priv inner: ~RtioPipe
|
||||
priv inner: StdSource
|
||||
}
|
||||
|
||||
impl Reader for StdReader {
|
||||
fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
|
||||
match self.inner.read(buf) {
|
||||
let ret = match self.inner {
|
||||
TTY(ref mut tty) => tty.read(buf),
|
||||
File(ref mut file) => file.read(buf).map_move(|i| i as uint),
|
||||
};
|
||||
match ret {
|
||||
Ok(amt) => Some(amt as uint),
|
||||
Err(e) => {
|
||||
io_error::cond.raise(e);
|
||||
|
@ -136,7 +169,7 @@ impl Reader for StdReader {
|
|||
|
||||
/// Representation of a writer to a standard output stream
|
||||
pub struct StdWriter {
|
||||
priv inner: ~RtioTTY
|
||||
priv inner: StdSource
|
||||
}
|
||||
|
||||
impl StdWriter {
|
||||
|
@ -151,10 +184,22 @@ impl StdWriter {
|
|||
/// This function will raise on the `io_error` condition if an error
|
||||
/// happens.
|
||||
pub fn winsize(&mut self) -> Option<(int, int)> {
|
||||
match self.inner.get_winsize() {
|
||||
Ok(p) => Some(p),
|
||||
Err(e) => {
|
||||
io_error::cond.raise(e);
|
||||
match self.inner {
|
||||
TTY(ref mut tty) => {
|
||||
match tty.get_winsize() {
|
||||
Ok(p) => Some(p),
|
||||
Err(e) => {
|
||||
io_error::cond.raise(e);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
File(*) => {
|
||||
io_error::cond.raise(IoError {
|
||||
kind: OtherIoError,
|
||||
desc: "stream is not a tty",
|
||||
detail: None,
|
||||
});
|
||||
None
|
||||
}
|
||||
}
|
||||
|
@ -168,21 +213,41 @@ impl StdWriter {
|
|||
/// This function will raise on the `io_error` condition if an error
|
||||
/// happens.
|
||||
pub fn set_raw(&mut self, raw: bool) {
|
||||
match self.inner.set_raw(raw) {
|
||||
Ok(()) => {},
|
||||
Err(e) => io_error::cond.raise(e),
|
||||
match self.inner {
|
||||
TTY(ref mut tty) => {
|
||||
match tty.set_raw(raw) {
|
||||
Ok(()) => {},
|
||||
Err(e) => io_error::cond.raise(e),
|
||||
}
|
||||
}
|
||||
File(*) => {
|
||||
io_error::cond.raise(IoError {
|
||||
kind: OtherIoError,
|
||||
desc: "stream is not a tty",
|
||||
detail: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether this tream is attached to a TTY instance or not.
|
||||
///
|
||||
/// This is similar to libc's isatty() function
|
||||
pub fn isatty(&self) -> bool { self.inner.isatty() }
|
||||
pub fn isatty(&self) -> bool {
|
||||
match self.inner {
|
||||
TTY(ref tty) => tty.isatty(),
|
||||
File(*) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Writer for StdWriter {
|
||||
fn write(&mut self, buf: &[u8]) {
|
||||
match self.inner.write(buf) {
|
||||
let ret = match self.inner {
|
||||
TTY(ref mut tty) => tty.write(buf),
|
||||
File(ref mut file) => file.write(buf),
|
||||
};
|
||||
match ret {
|
||||
Ok(()) => {}
|
||||
Err(e) => io_error::cond.raise(e)
|
||||
}
|
||||
|
|
|
@ -58,6 +58,20 @@ pub struct FileOpenConfig {
|
|||
priv mode: int
|
||||
}
|
||||
|
||||
/// Description of what to do when a file handle is closed
|
||||
pub enum CloseBehavior {
|
||||
/// Do not close this handle when the object is destroyed
|
||||
DontClose,
|
||||
/// Synchronously close the handle, meaning that the task will block when
|
||||
/// the handle is destroyed until it has been fully closed.
|
||||
CloseSynchronously,
|
||||
/// Asynchronously closes a handle, meaning that the task will *not* block
|
||||
/// when the handle is destroyed, but the handle will still get deallocated
|
||||
/// and cleaned up (but this will happen asynchronously on the local event
|
||||
/// loop).
|
||||
CloseAsynchronously,
|
||||
}
|
||||
|
||||
pub fn with_local_io<T>(f: &fn(&mut IoFactory) -> Option<T>) -> Option<T> {
|
||||
use rt::sched::Scheduler;
|
||||
use rt::local::Local;
|
||||
|
@ -84,7 +98,7 @@ pub trait IoFactory {
|
|||
fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>,
|
||||
hint: Option<ai::Hint>) -> Result<~[ai::Info], IoError>;
|
||||
fn timer_init(&mut self) -> Result<~RtioTimer, IoError>;
|
||||
fn fs_from_raw_fd(&mut self, fd: c_int, close_on_drop: bool) -> ~RtioFileStream;
|
||||
fn fs_from_raw_fd(&mut self, fd: c_int, close: CloseBehavior) -> ~RtioFileStream;
|
||||
fn fs_open(&mut self, path: &CString, fm: FileMode, fa: FileAccess)
|
||||
-> Result<~RtioFileStream, IoError>;
|
||||
fn fs_unlink(&mut self, path: &CString) -> Result<(), IoError>;
|
||||
|
|
|
@ -479,7 +479,6 @@ pub extern "C" fn rust_stack_exhausted() {
|
|||
use rt::in_green_task_context;
|
||||
use rt::task::Task;
|
||||
use rt::local::Local;
|
||||
use rt::logging::Logger;
|
||||
use unstable::intrinsics;
|
||||
|
||||
unsafe {
|
||||
|
@ -529,8 +528,12 @@ pub extern "C" fn rust_stack_exhausted() {
|
|||
do Local::borrow |task: &mut Task| {
|
||||
let n = task.name.as_ref().map(|n| n.as_slice()).unwrap_or("<unnamed>");
|
||||
|
||||
format_args!(|args| { task.logger.log(args) },
|
||||
"task '{}' has overflowed its stack", n);
|
||||
// See the message below for why this is not emitted to the
|
||||
// task's logger. This has the additional conundrum of the
|
||||
// logger may not be initialized just yet, meaning that an FFI
|
||||
// call would happen to initialized it (calling out to libuv),
|
||||
// and the FFI call needs 2MB of stack when we just ran out.
|
||||
rterrln!("task '{}' has overflowed its stack", n);
|
||||
}
|
||||
} else {
|
||||
rterrln!("stack overflow in non-task context");
|
||||
|
|
|
@ -43,10 +43,11 @@ impl FsRequest {
|
|||
let mut me = self;
|
||||
me.req_boilerplate(Some(cb))
|
||||
};
|
||||
path.with_ref(|p| unsafe {
|
||||
let ret = path.with_ref(|p| unsafe {
|
||||
uvll::fs_open(loop_.native_handle(),
|
||||
self.native_handle(), p, flags, mode, complete_cb_ptr)
|
||||
});
|
||||
assert_eq!(ret, 0);
|
||||
}
|
||||
|
||||
pub fn open_sync(self, loop_: &Loop, path: &CString,
|
||||
|
@ -67,10 +68,11 @@ impl FsRequest {
|
|||
let mut me = self;
|
||||
me.req_boilerplate(Some(cb))
|
||||
};
|
||||
path.with_ref(|p| unsafe {
|
||||
let ret = path.with_ref(|p| unsafe {
|
||||
uvll::fs_unlink(loop_.native_handle(),
|
||||
self.native_handle(), p, complete_cb_ptr)
|
||||
});
|
||||
assert_eq!(ret, 0);
|
||||
}
|
||||
|
||||
pub fn unlink_sync(self, loop_: &Loop, path: &CString)
|
||||
|
@ -91,10 +93,11 @@ impl FsRequest {
|
|||
let mut me = self;
|
||||
me.req_boilerplate(Some(cb))
|
||||
};
|
||||
path.with_ref(|p| unsafe {
|
||||
let ret = path.with_ref(|p| unsafe {
|
||||
uvll::fs_stat(loop_.native_handle(),
|
||||
self.native_handle(), p, complete_cb_ptr)
|
||||
});
|
||||
assert_eq!(ret, 0);
|
||||
}
|
||||
|
||||
pub fn write(self, loop_: &Loop, fd: c_int, buf: Buf, offset: i64, cb: FsCallback) {
|
||||
|
@ -104,11 +107,12 @@ impl FsRequest {
|
|||
};
|
||||
let base_ptr = buf.base as *c_void;
|
||||
let len = buf.len as uint;
|
||||
unsafe {
|
||||
let ret = unsafe {
|
||||
uvll::fs_write(loop_.native_handle(), self.native_handle(),
|
||||
fd, base_ptr,
|
||||
len, offset, complete_cb_ptr)
|
||||
};
|
||||
assert_eq!(ret, 0);
|
||||
}
|
||||
pub fn write_sync(self, loop_: &Loop, fd: c_int, buf: Buf, offset: i64)
|
||||
-> Result<c_int, UvError> {
|
||||
|
@ -133,11 +137,12 @@ impl FsRequest {
|
|||
};
|
||||
let buf_ptr = buf.base as *c_void;
|
||||
let len = buf.len as uint;
|
||||
unsafe {
|
||||
let ret = unsafe {
|
||||
uvll::fs_read(loop_.native_handle(), self.native_handle(),
|
||||
fd, buf_ptr,
|
||||
len, offset, complete_cb_ptr)
|
||||
};
|
||||
assert_eq!(ret, 0);
|
||||
}
|
||||
pub fn read_sync(self, loop_: &Loop, fd: c_int, buf: Buf, offset: i64)
|
||||
-> Result<c_int, UvError> {
|
||||
|
@ -160,10 +165,11 @@ impl FsRequest {
|
|||
let mut me = self;
|
||||
me.req_boilerplate(Some(cb))
|
||||
};
|
||||
unsafe {
|
||||
let ret = unsafe {
|
||||
uvll::fs_close(loop_.native_handle(), self.native_handle(),
|
||||
fd, complete_cb_ptr)
|
||||
};
|
||||
assert_eq!(ret, 0);
|
||||
}
|
||||
pub fn close_sync(self, loop_: &Loop, fd: c_int) -> Result<c_int, UvError> {
|
||||
let complete_cb_ptr = {
|
||||
|
@ -182,10 +188,11 @@ impl FsRequest {
|
|||
let mut me = self;
|
||||
me.req_boilerplate(Some(cb))
|
||||
};
|
||||
path.with_ref(|p| unsafe {
|
||||
let ret = path.with_ref(|p| unsafe {
|
||||
uvll::fs_mkdir(loop_.native_handle(),
|
||||
self.native_handle(), p, mode, complete_cb_ptr)
|
||||
self.native_handle(), p, mode, complete_cb_ptr)
|
||||
});
|
||||
assert_eq!(ret, 0);
|
||||
}
|
||||
|
||||
pub fn rmdir(self, loop_: &Loop, path: &CString, cb: FsCallback) {
|
||||
|
@ -193,10 +200,11 @@ impl FsRequest {
|
|||
let mut me = self;
|
||||
me.req_boilerplate(Some(cb))
|
||||
};
|
||||
path.with_ref(|p| unsafe {
|
||||
let ret = path.with_ref(|p| unsafe {
|
||||
uvll::fs_rmdir(loop_.native_handle(),
|
||||
self.native_handle(), p, complete_cb_ptr)
|
||||
self.native_handle(), p, complete_cb_ptr)
|
||||
});
|
||||
assert_eq!(ret, 0);
|
||||
}
|
||||
|
||||
pub fn readdir(self, loop_: &Loop, path: &CString,
|
||||
|
@ -205,10 +213,11 @@ impl FsRequest {
|
|||
let mut me = self;
|
||||
me.req_boilerplate(Some(cb))
|
||||
};
|
||||
path.with_ref(|p| unsafe {
|
||||
let ret = path.with_ref(|p| unsafe {
|
||||
uvll::fs_readdir(loop_.native_handle(),
|
||||
self.native_handle(), p, flags, complete_cb_ptr)
|
||||
self.native_handle(), p, flags, complete_cb_ptr)
|
||||
});
|
||||
assert_eq!(ret, 0);
|
||||
}
|
||||
|
||||
// accessors/utility funcs
|
||||
|
|
|
@ -20,9 +20,9 @@ impl Watcher for IdleWatcher { }
|
|||
impl IdleWatcher {
|
||||
pub fn new(loop_: &mut Loop) -> IdleWatcher {
|
||||
unsafe {
|
||||
let handle = uvll::idle_new();
|
||||
let handle = uvll::malloc_handle(uvll::UV_IDLE);
|
||||
assert!(handle.is_not_null());
|
||||
assert!(0 == uvll::idle_init(loop_.native_handle(), handle));
|
||||
assert_eq!(uvll::idle_init(loop_.native_handle(), handle), 0);
|
||||
let mut watcher: IdleWatcher = NativeHandle::from_native_handle(handle);
|
||||
watcher.install_watcher_data();
|
||||
return watcher
|
||||
|
@ -36,29 +36,14 @@ impl IdleWatcher {
|
|||
}
|
||||
|
||||
unsafe {
|
||||
assert!(0 == uvll::idle_start(self.native_handle(), idle_cb))
|
||||
};
|
||||
|
||||
extern fn idle_cb(handle: *uvll::uv_idle_t, status: c_int) {
|
||||
let mut idle_watcher: IdleWatcher = NativeHandle::from_native_handle(handle);
|
||||
let data = idle_watcher.get_watcher_data();
|
||||
let cb: &IdleCallback = data.idle_cb.get_ref();
|
||||
let status = status_to_maybe_uv_error(status);
|
||||
(*cb)(idle_watcher, status);
|
||||
assert_eq!(uvll::idle_start(self.native_handle(), idle_cb), 0)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn restart(&mut self) {
|
||||
unsafe {
|
||||
assert!(0 == uvll::idle_start(self.native_handle(), idle_cb))
|
||||
};
|
||||
|
||||
extern fn idle_cb(handle: *uvll::uv_idle_t, status: c_int) {
|
||||
let mut idle_watcher: IdleWatcher = NativeHandle::from_native_handle(handle);
|
||||
let data = idle_watcher.get_watcher_data();
|
||||
let cb: &IdleCallback = data.idle_cb.get_ref();
|
||||
let status = status_to_maybe_uv_error(status);
|
||||
(*cb)(idle_watcher, status);
|
||||
assert!(self.get_watcher_data().idle_cb.is_some());
|
||||
assert_eq!(uvll::idle_start(self.native_handle(), idle_cb), 0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,7 +53,7 @@ impl IdleWatcher {
|
|||
// free
|
||||
|
||||
unsafe {
|
||||
assert!(0 == uvll::idle_stop(self.native_handle()));
|
||||
assert_eq!(uvll::idle_stop(self.native_handle()), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -82,6 +67,14 @@ impl NativeHandle<*uvll::uv_idle_t> for IdleWatcher {
|
|||
}
|
||||
}
|
||||
|
||||
extern fn idle_cb(handle: *uvll::uv_idle_t, status: c_int) {
|
||||
let mut idle_watcher: IdleWatcher = NativeHandle::from_native_handle(handle);
|
||||
let data = idle_watcher.get_watcher_data();
|
||||
let cb: &IdleCallback = data.idle_cb.get_ref();
|
||||
let status = status_to_maybe_uv_error(status);
|
||||
(*cb)(idle_watcher, status);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ impl SignalWatcher {
|
|||
let mut watcher: SignalWatcher = NativeHandle::from_native_handle(handle);
|
||||
let data = watcher.get_watcher_data();
|
||||
let cb = data.signal_cb.get_ref();
|
||||
(*cb)(watcher, unsafe { cast::transmute(signum as i64) });
|
||||
(*cb)(watcher, unsafe { cast::transmute(signum as int) });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -547,10 +547,10 @@ impl IoFactory for UvIoFactory {
|
|||
Ok(~UvTimer::new(watcher, home) as ~RtioTimer)
|
||||
}
|
||||
|
||||
fn fs_from_raw_fd(&mut self, fd: c_int, close_on_drop: bool) -> ~RtioFileStream {
|
||||
fn fs_from_raw_fd(&mut self, fd: c_int, close: CloseBehavior) -> ~RtioFileStream {
|
||||
let loop_ = Loop {handle: self.uv_loop().native_handle()};
|
||||
let home = get_handle_to_current_scheduler!();
|
||||
~UvFileStream::new(loop_, fd, close_on_drop, home) as ~RtioFileStream
|
||||
~UvFileStream::new(loop_, fd, close, home) as ~RtioFileStream
|
||||
}
|
||||
|
||||
fn fs_open(&mut self, path: &CString, fm: FileMode, fa: FileAccess)
|
||||
|
@ -590,7 +590,7 @@ impl IoFactory for UvIoFactory {
|
|||
let home = get_handle_to_current_scheduler!();
|
||||
let fd = req.get_result() as c_int;
|
||||
let fs = ~UvFileStream::new(
|
||||
loop_, fd, true, home) as ~RtioFileStream;
|
||||
loop_, fd, CloseSynchronously, home) as ~RtioFileStream;
|
||||
let res = Ok(fs);
|
||||
unsafe { (*result_cell_ptr).put_back(res); }
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
|
@ -1482,8 +1482,8 @@ impl RtioTimer for UvTimer {
|
|||
pub struct UvFileStream {
|
||||
priv loop_: Loop,
|
||||
priv fd: c_int,
|
||||
priv close_on_drop: bool,
|
||||
priv home: SchedHandle
|
||||
priv close: CloseBehavior,
|
||||
priv home: SchedHandle,
|
||||
}
|
||||
|
||||
impl HomingIO for UvFileStream {
|
||||
|
@ -1491,13 +1491,13 @@ impl HomingIO for UvFileStream {
|
|||
}
|
||||
|
||||
impl UvFileStream {
|
||||
fn new(loop_: Loop, fd: c_int, close_on_drop: bool,
|
||||
fn new(loop_: Loop, fd: c_int, close: CloseBehavior,
|
||||
home: SchedHandle) -> UvFileStream {
|
||||
UvFileStream {
|
||||
loop_: loop_,
|
||||
fd: fd,
|
||||
close_on_drop: close_on_drop,
|
||||
home: home
|
||||
close: close,
|
||||
home: home,
|
||||
}
|
||||
}
|
||||
fn base_read(&mut self, buf: &mut [u8], offset: i64) -> Result<int, IoError> {
|
||||
|
@ -1517,9 +1517,9 @@ impl UvFileStream {
|
|||
unsafe { (*result_cell_ptr).put_back(res); }
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
scheduler.resume_blocked_task_immediately(task_cell.take());
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
result_cell.take()
|
||||
}
|
||||
fn base_write(&mut self, buf: &[u8], offset: i64) -> Result<(), IoError> {
|
||||
|
@ -1539,9 +1539,9 @@ impl UvFileStream {
|
|||
unsafe { (*result_cell_ptr).put_back(res); }
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
scheduler.resume_blocked_task_immediately(task_cell.take());
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
result_cell.take()
|
||||
}
|
||||
fn seek_common(&mut self, pos: i64, whence: c_int) ->
|
||||
|
@ -1564,16 +1564,23 @@ impl UvFileStream {
|
|||
|
||||
impl Drop for UvFileStream {
|
||||
fn drop(&mut self) {
|
||||
if self.close_on_drop {
|
||||
do self.home_for_io_with_sched |self_, scheduler| {
|
||||
do scheduler.deschedule_running_task_and_then |_, task| {
|
||||
let task_cell = Cell::new(task);
|
||||
let close_req = file::FsRequest::new();
|
||||
do close_req.close(&self_.loop_, self_.fd) |_,_| {
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
scheduler.resume_blocked_task_immediately(task_cell.take());
|
||||
};
|
||||
};
|
||||
match self.close {
|
||||
DontClose => {}
|
||||
CloseAsynchronously => {
|
||||
let close_req = file::FsRequest::new();
|
||||
do close_req.close(&self.loop_, self.fd) |_,_| {}
|
||||
}
|
||||
CloseSynchronously => {
|
||||
do self.home_for_io_with_sched |self_, scheduler| {
|
||||
do scheduler.deschedule_running_task_and_then |_, task| {
|
||||
let task_cell = Cell::new(task);
|
||||
let close_req = file::FsRequest::new();
|
||||
do close_req.close(&self_.loop_, self_.fd) |_,_| {
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
scheduler.resume_blocked_task_immediately(task_cell.take());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1750,7 +1757,6 @@ impl Drop for UvTTY {
|
|||
// scheduler isn't available, so we can't do the normal "take the
|
||||
// scheduler and resume once close is done". Instead close operations on
|
||||
// a TTY are asynchronous.
|
||||
|
||||
self.tty.close_async();
|
||||
}
|
||||
}
|
||||
|
@ -2465,7 +2471,7 @@ fn uvio_naive_print(input: &str) {
|
|||
use libc::{STDOUT_FILENO};
|
||||
let io = local_io();
|
||||
{
|
||||
let mut fd = io.fs_from_raw_fd(STDOUT_FILENO, false);
|
||||
let mut fd = io.fs_from_raw_fd(STDOUT_FILENO, DontClose);
|
||||
let write_buf = input.as_bytes();
|
||||
fd.write(write_buf);
|
||||
}
|
||||
|
|
|
@ -235,37 +235,37 @@ pub type socklen_t = c_int;
|
|||
#[cfg(target_os = "android")]
|
||||
#[cfg(target_os = "linux")]
|
||||
pub struct addrinfo {
|
||||
priv ai_flags: c_int,
|
||||
priv ai_family: c_int,
|
||||
priv ai_socktype: c_int,
|
||||
priv ai_protocol: c_int,
|
||||
priv ai_addrlen: socklen_t,
|
||||
ai_flags: c_int,
|
||||
ai_family: c_int,
|
||||
ai_socktype: c_int,
|
||||
ai_protocol: c_int,
|
||||
ai_addrlen: socklen_t,
|
||||
ai_addr: *sockaddr,
|
||||
priv ai_canonname: *char,
|
||||
ai_canonname: *char,
|
||||
ai_next: *addrinfo
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[cfg(target_os = "freebsd")]
|
||||
pub struct addrinfo {
|
||||
priv ai_flags: c_int,
|
||||
priv ai_family: c_int,
|
||||
priv ai_socktype: c_int,
|
||||
priv ai_protocol: c_int,
|
||||
priv ai_addrlen: socklen_t,
|
||||
priv ai_canonname: *char,
|
||||
ai_flags: c_int,
|
||||
ai_family: c_int,
|
||||
ai_socktype: c_int,
|
||||
ai_protocol: c_int,
|
||||
ai_addrlen: socklen_t,
|
||||
ai_canonname: *char,
|
||||
ai_addr: *sockaddr,
|
||||
ai_next: *addrinfo
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub struct addrinfo {
|
||||
priv ai_flags: c_int,
|
||||
priv ai_family: c_int,
|
||||
priv ai_socktype: c_int,
|
||||
priv ai_protocol: c_int,
|
||||
priv ai_addrlen: size_t,
|
||||
priv ai_canonname: *char,
|
||||
ai_flags: c_int,
|
||||
ai_family: c_int,
|
||||
ai_socktype: c_int,
|
||||
ai_protocol: c_int,
|
||||
ai_addrlen: size_t,
|
||||
ai_canonname: *char,
|
||||
ai_addr: *sockaddr,
|
||||
ai_next: *addrinfo
|
||||
}
|
||||
|
@ -423,18 +423,6 @@ pub unsafe fn walk(loop_handle: *c_void, cb: uv_walk_cb, arg: *c_void) {
|
|||
rust_uv_walk(loop_handle, cb, arg);
|
||||
}
|
||||
|
||||
pub unsafe fn idle_new() -> *uv_idle_t {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
rust_uv_idle_new()
|
||||
}
|
||||
|
||||
pub unsafe fn idle_delete(handle: *uv_idle_t) {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
rust_uv_idle_delete(handle)
|
||||
}
|
||||
|
||||
pub unsafe fn idle_init(loop_handle: *uv_loop_t, handle: *uv_idle_t) -> c_int {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
|
@ -1028,8 +1016,6 @@ extern {
|
|||
fn rust_uv_close(handle: *c_void, cb: uv_close_cb);
|
||||
fn rust_uv_walk(loop_handle: *c_void, cb: uv_walk_cb, arg: *c_void);
|
||||
|
||||
fn rust_uv_idle_new() -> *uv_idle_t;
|
||||
fn rust_uv_idle_delete(handle: *uv_idle_t);
|
||||
fn rust_uv_idle_init(loop_handle: *uv_loop_t, handle: *uv_idle_t) -> c_int;
|
||||
fn rust_uv_idle_start(handle: *uv_idle_t, cb: uv_idle_cb) -> c_int;
|
||||
fn rust_uv_idle_stop(handle: *uv_idle_t) -> c_int;
|
||||
|
|
|
@ -219,16 +219,27 @@ impl Process {
|
|||
let (p, ch) = stream();
|
||||
let ch = SharedChan::new(ch);
|
||||
let ch_clone = ch.clone();
|
||||
do task::spawn_sched(task::SingleThreaded) {
|
||||
match error.take() {
|
||||
Some(ref mut e) => ch.send((2, e.read_to_end())),
|
||||
None => ch.send((2, ~[]))
|
||||
|
||||
// FIXME(#910, #8674): right now I/O is incredibly brittle when it comes
|
||||
// to linked failure, so these tasks must be spawn so they're not
|
||||
// affected by linked failure. If these are removed, then the
|
||||
// runtime may never exit because linked failure will cause some
|
||||
// SchedHandle structures to not get destroyed, meaning that
|
||||
// there's always an async watcher available.
|
||||
do task::spawn_unlinked {
|
||||
do io::ignore_io_error {
|
||||
match error.take() {
|
||||
Some(ref mut e) => ch.send((2, e.read_to_end())),
|
||||
None => ch.send((2, ~[]))
|
||||
}
|
||||
}
|
||||
}
|
||||
do task::spawn_sched(task::SingleThreaded) {
|
||||
match output.take() {
|
||||
Some(ref mut e) => ch_clone.send((1, e.read_to_end())),
|
||||
None => ch_clone.send((1, ~[]))
|
||||
do task::spawn_unlinked {
|
||||
do io::ignore_io_error {
|
||||
match output.take() {
|
||||
Some(ref mut e) => ch_clone.send((1, e.read_to_end())),
|
||||
None => ch_clone.send((1, ~[]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -466,16 +466,6 @@ rust_uv_addrinfo_as_sockaddr_in6(addrinfo* input) {
|
|||
return (sockaddr_in6*)input->ai_addr;
|
||||
}
|
||||
|
||||
extern "C" uv_idle_t*
|
||||
rust_uv_idle_new() {
|
||||
return new uv_idle_t;
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
rust_uv_idle_delete(uv_idle_t* handle) {
|
||||
delete handle;
|
||||
}
|
||||
|
||||
extern "C" int
|
||||
rust_uv_idle_init(uv_loop_t* loop, uv_idle_t* idle) {
|
||||
return uv_idle_init(loop, idle);
|
||||
|
|
|
@ -98,8 +98,6 @@ rust_uv_get_base_from_buf
|
|||
rust_uv_get_len_from_buf
|
||||
rust_uv_getaddrinfo
|
||||
rust_uv_freeaddrinfo
|
||||
rust_uv_idle_new
|
||||
rust_uv_idle_delete
|
||||
rust_uv_idle_init
|
||||
rust_uv_idle_start
|
||||
rust_uv_idle_stop
|
||||
|
|
Loading…
Reference in New Issue