Skip to content

Commit 1ed130a

Browse files
committed
Another round of test fixes and merge conflicts
1 parent fb168b4 commit 1ed130a

File tree

11 files changed

+234
-121
lines changed

11 files changed

+234
-121
lines changed

src/libextra/url.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ fn decode_inner(s: &str, full_url: bool) -> ~str {
145145
let mut bytes = [0, 0];
146146
match rdr.read(bytes) {
147147
Some(2) => {}
148-
_ => fail2!() // XXX: malformed url?
148+
_ => fail!() // XXX: malformed url?
149149
}
150150
let ch = uint::parse_bytes(bytes, 16u).unwrap() as u8 as char;
151151

@@ -279,7 +279,7 @@ pub fn decode_form_urlencoded(s: &[u8]) -> HashMap<~str, ~[~str]> {
279279
let mut bytes = [0, 0];
280280
match rdr.read(bytes) {
281281
Some(2) => {}
282-
_ => fail2!() // XXX: malformed?
282+
_ => fail!() // XXX: malformed?
283283
}
284284
uint::parse_bytes(bytes, 16u).unwrap() as u8 as char
285285
}

src/librustpkg/tests.rs

+12-7
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@
1111
// rustpkg unit tests
1212

1313
use context::{BuildContext, Context, RustcFlags};
14-
use std::{io, os, run, str, task};
14+
use std::{os, run, str, task};
15+
use std::rt::io;
16+
use std::rt::io::Writer;
17+
use std::rt::io::file::FileInfo;
1518
use extra::arc::Arc;
1619
use extra::arc::RWArc;
1720
use extra::tempfile::TempDir;
@@ -81,8 +84,9 @@ fn git_repo_pkg_with_tag(a_tag: ~str) -> PkgId {
8184
}
8285

8386
fn writeFile(file_path: &Path, contents: &str) {
84-
let out = io::file_writer(file_path, [io::Create, io::Truncate]).unwrap();
85-
out.write_line(contents);
87+
let mut out = file_path.open_writer(io::CreateOrTruncate);
88+
out.write(contents.as_bytes());
89+
out.write(['\n' as u8]);
8690
}
8791

8892
fn mk_emptier_workspace(tag: &str) -> TempDir {
@@ -550,10 +554,11 @@ fn frob_source_file(workspace: &Path, pkgid: &PkgId, filename: &str) {
550554
debug!("Frobbed? {:?}", maybe_p);
551555
match maybe_p {
552556
Some(ref p) => {
553-
let w = io::file_writer(p, &[io::Append]);
554-
match w {
555-
Err(s) => { let _ = cond.raise((p.clone(), format!("Bad path: {}", s))); }
556-
Ok(w) => w.write_line("/* hi */")
557+
do io::io_error::cond.trap(|e| {
558+
cond.raise((p.clone(), format!("Bad path: {}", e.desc)));
559+
}).inside {
560+
let mut w = p.open_writer(io::Append);
561+
w.write(bytes!("/* hi */\n"));
557562
}
558563
}
559564
None => fail!("frob_source_file failed to find a source file in {}",

src/libstd/rt/io/signal.rs

+16-9
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ impl Listener {
147147
mod test {
148148
use libc;
149149
use rt::io::timer;
150+
use rt::io;
150151
use super::*;
151152

152153
// kill is only available on Unixes
@@ -158,19 +159,19 @@ mod test {
158159
}
159160
}
160161

161-
#[test]
162+
#[test] #[cfg(unix)]
162163
fn test_io_signal_smoketest() {
163164
let mut signal = Listener::new();
164165
signal.register(Interrupt);
165166
sigint();
166167
timer::sleep(10);
167168
match signal.port.recv() {
168169
Interrupt => (),
169-
s => fail2!("Expected Interrupt, got {:?}", s),
170+
s => fail!("Expected Interrupt, got {:?}", s),
170171
}
171172
}
172173

173-
#[test]
174+
#[test] #[cfg(unix)]
174175
fn test_io_signal_two_signal_one_signum() {
175176
let mut s1 = Listener::new();
176177
let mut s2 = Listener::new();
@@ -180,15 +181,15 @@ mod test {
180181
timer::sleep(10);
181182
match s1.port.recv() {
182183
Interrupt => (),
183-
s => fail2!("Expected Interrupt, got {:?}", s),
184+
s => fail!("Expected Interrupt, got {:?}", s),
184185
}
185186
match s1.port.recv() {
186187
Interrupt => (),
187-
s => fail2!("Expected Interrupt, got {:?}", s),
188+
s => fail!("Expected Interrupt, got {:?}", s),
188189
}
189190
}
190191

191-
#[test]
192+
#[test] #[cfg(unix)]
192193
fn test_io_signal_unregister() {
193194
let mut s1 = Listener::new();
194195
let mut s2 = Listener::new();
@@ -198,16 +199,22 @@ mod test {
198199
sigint();
199200
timer::sleep(10);
200201
if s2.port.peek() {
201-
fail2!("Unexpected {:?}", s2.port.recv());
202+
fail!("Unexpected {:?}", s2.port.recv());
202203
}
203204
}
204205

205206
#[cfg(windows)]
206207
#[test]
207208
fn test_io_signal_invalid_signum() {
208209
let mut s = Listener::new();
209-
if s.register(User1) {
210-
fail2!("Unexpected successful registry of signum {:?}", User1);
210+
let mut called = false;
211+
do io::io_error::cond.trap(|_| {
212+
called = true;
213+
}).inside {
214+
if s.register(User1) {
215+
fail!("Unexpected successful registry of signum {:?}", User1);
216+
}
211217
}
218+
assert!(called);
212219
}
213220
}

src/libstd/rt/io/stdio.rs

+99-34
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,57 @@ use fmt;
3030
use libc;
3131
use option::{Option, Some, None};
3232
use result::{Ok, Err};
33-
use rt::rtio::{IoFactory, RtioTTY, with_local_io, RtioPipe};
34-
use super::{Reader, Writer, io_error};
33+
use rt::rtio::{IoFactory, RtioTTY, RtioFileStream, with_local_io,
34+
CloseAsynchronously};
35+
use super::{Reader, Writer, io_error, IoError, OtherIoError};
36+
37+
// And so begins the tale of acquiring a uv handle to a stdio stream on all
38+
// platforms in all situations. Our story begins by splitting the world into two
39+
// categories, windows and unix. Then one day the creators of unix said let
40+
// there be redirection! And henceforth there was redirection away from the
41+
// console for standard I/O streams.
42+
//
43+
// After this day, the world split into four factions:
44+
//
45+
// 1. Unix with stdout on a terminal.
46+
// 2. Unix with stdout redirected.
47+
// 3. Windows with stdout on a terminal.
48+
// 4. Windows with stdout redirected.
49+
//
50+
// Many years passed, and then one day the nation of libuv decided to unify this
51+
// world. After months of toiling, uv created three ideas: TTY, Pipe, File.
52+
// These three ideas propagated throughout the lands and the four great factions
53+
// decided to settle among them.
54+
//
55+
// The groups of 1, 2, and 3 all worked very hard towards the idea of TTY. Upon
56+
// doing so, they even enhanced themselves further then their Pipe/File
57+
// brethren, becoming the dominant powers.
58+
//
59+
// The group of 4, however, decided to work independently. They abandoned the
60+
// common TTY belief throughout, and even abandoned the fledgling Pipe belief.
61+
// The members of the 4th faction decided to only align themselves with File.
62+
//
63+
// tl;dr; TTY works on everything but when windows stdout is redirected, in that
64+
// case pipe also doesn't work, but magically file does!
65+
enum StdSource {
66+
TTY(~RtioTTY),
67+
File(~RtioFileStream),
68+
}
3569

3670
#[fixed_stack_segment] #[inline(never)]
37-
fn tty<T>(fd: libc::c_int, f: &fn(~RtioTTY) -> T) -> T {
71+
fn src<T>(fd: libc::c_int, readable: bool, f: &fn(StdSource) -> T) -> T {
3872
do with_local_io |io| {
39-
// Always pass in readable as true, otherwise libuv turns our writes
40-
// into blocking writes. We also need to dup the file descriptor because
41-
// the tty will be closed when it's dropped.
42-
match io.tty_open(unsafe { libc::dup(fd) }, true) {
43-
Ok(tty) => Some(f(tty)),
44-
Err(e) => {
45-
io_error::cond.raise(e);
46-
None
73+
let fd = unsafe { libc::dup(fd) };
74+
match io.tty_open(fd, readable) {
75+
Ok(tty) => Some(f(TTY(tty))),
76+
Err(_) => {
77+
// It's not really that desirable if these handles are closed
78+
// synchronously, and because they're squirreled away in a task
79+
// structure the destructors will be run when the task is
80+
// attempted to get destroyed. This means that if we run a
81+
// synchronous destructor we'll attempt to do some scheduling
82+
// operations which will just result in sadness.
83+
Some(f(File(io.fs_from_raw_fd(fd, CloseAsynchronously))))
4784
}
4885
}
4986
}.unwrap()
@@ -54,15 +91,7 @@ fn tty<T>(fd: libc::c_int, f: &fn(~RtioTTY) -> T) -> T {
5491
/// See `stdout()` for notes about this function.
5592
#[fixed_stack_segment] #[inline(never)]
5693
pub fn stdin() -> StdReader {
57-
do with_local_io |io| {
58-
match io.pipe_open(unsafe { libc::dup(libc::STDIN_FILENO) }) {
59-
Ok(stream) => Some(StdReader { inner: stream }),
60-
Err(e) => {
61-
io_error::cond.raise(e);
62-
None
63-
}
64-
}
65-
}.unwrap()
94+
do src(libc::STDIN_FILENO, true) |src| { StdReader { inner: src } }
6695
}
6796

6897
/// Creates a new non-blocking handle to the stdout of the current process.
@@ -72,14 +101,14 @@ pub fn stdin() -> StdReader {
72101
/// task context because the stream returned will be a non-blocking object using
73102
/// the local scheduler to perform the I/O.
74103
pub fn stdout() -> StdWriter {
75-
do tty(libc::STDOUT_FILENO) |tty| { StdWriter { inner: tty } }
104+
do src(libc::STDOUT_FILENO, false) |src| { StdWriter { inner: src } }
76105
}
77106

78107
/// Creates a new non-blocking handle to the stderr of the current process.
79108
///
80109
/// See `stdout()` for notes about this function.
81110
pub fn stderr() -> StdWriter {
82-
do tty(libc::STDERR_FILENO) |tty| { StdWriter { inner: tty } }
111+
do src(libc::STDERR_FILENO, false) |src| { StdWriter { inner: src } }
83112
}
84113

85114
/// 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) {
117146

118147
/// Representation of a reader of a standard input stream
119148
pub struct StdReader {
120-
priv inner: ~RtioPipe
149+
priv inner: StdSource
121150
}
122151

123152
impl Reader for StdReader {
124153
fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
125-
match self.inner.read(buf) {
154+
let ret = match self.inner {
155+
TTY(ref mut tty) => tty.read(buf),
156+
File(ref mut file) => file.read(buf).map_move(|i| i as uint),
157+
};
158+
match ret {
126159
Ok(amt) => Some(amt as uint),
127160
Err(e) => {
128161
io_error::cond.raise(e);
@@ -136,7 +169,7 @@ impl Reader for StdReader {
136169

137170
/// Representation of a writer to a standard output stream
138171
pub struct StdWriter {
139-
priv inner: ~RtioTTY
172+
priv inner: StdSource
140173
}
141174

142175
impl StdWriter {
@@ -151,10 +184,22 @@ impl StdWriter {
151184
/// This function will raise on the `io_error` condition if an error
152185
/// happens.
153186
pub fn winsize(&mut self) -> Option<(int, int)> {
154-
match self.inner.get_winsize() {
155-
Ok(p) => Some(p),
156-
Err(e) => {
157-
io_error::cond.raise(e);
187+
match self.inner {
188+
TTY(ref mut tty) => {
189+
match tty.get_winsize() {
190+
Ok(p) => Some(p),
191+
Err(e) => {
192+
io_error::cond.raise(e);
193+
None
194+
}
195+
}
196+
}
197+
File(*) => {
198+
io_error::cond.raise(IoError {
199+
kind: OtherIoError,
200+
desc: "stream is not a tty",
201+
detail: None,
202+
});
158203
None
159204
}
160205
}
@@ -168,21 +213,41 @@ impl StdWriter {
168213
/// This function will raise on the `io_error` condition if an error
169214
/// happens.
170215
pub fn set_raw(&mut self, raw: bool) {
171-
match self.inner.set_raw(raw) {
172-
Ok(()) => {},
173-
Err(e) => io_error::cond.raise(e),
216+
match self.inner {
217+
TTY(ref mut tty) => {
218+
match tty.set_raw(raw) {
219+
Ok(()) => {},
220+
Err(e) => io_error::cond.raise(e),
221+
}
222+
}
223+
File(*) => {
224+
io_error::cond.raise(IoError {
225+
kind: OtherIoError,
226+
desc: "stream is not a tty",
227+
detail: None,
228+
});
229+
}
174230
}
175231
}
176232

177233
/// Returns whether this tream is attached to a TTY instance or not.
178234
///
179235
/// This is similar to libc's isatty() function
180-
pub fn isatty(&self) -> bool { self.inner.isatty() }
236+
pub fn isatty(&self) -> bool {
237+
match self.inner {
238+
TTY(ref tty) => tty.isatty(),
239+
File(*) => false,
240+
}
241+
}
181242
}
182243

183244
impl Writer for StdWriter {
184245
fn write(&mut self, buf: &[u8]) {
185-
match self.inner.write(buf) {
246+
let ret = match self.inner {
247+
TTY(ref mut tty) => tty.write(buf),
248+
File(ref mut file) => file.write(buf),
249+
};
250+
match ret {
186251
Ok(()) => {}
187252
Err(e) => io_error::cond.raise(e)
188253
}

src/libstd/rt/rtio.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,20 @@ pub struct FileOpenConfig {
5858
priv mode: int
5959
}
6060

61+
/// Description of what to do when a file handle is closed
62+
pub enum CloseBehavior {
63+
/// Do not close this handle when the object is destroyed
64+
DontClose,
65+
/// Synchronously close the handle, meaning that the task will block when
66+
/// the handle is destroyed until it has been fully closed.
67+
CloseSynchronously,
68+
/// Asynchronously closes a handle, meaning that the task will *not* block
69+
/// when the handle is destroyed, but the handle will still get deallocated
70+
/// and cleaned up (but this will happen asynchronously on the local event
71+
/// loop).
72+
CloseAsynchronously,
73+
}
74+
6175
pub fn with_local_io<T>(f: &fn(&mut IoFactory) -> Option<T>) -> Option<T> {
6276
use rt::sched::Scheduler;
6377
use rt::local::Local;
@@ -84,7 +98,7 @@ pub trait IoFactory {
8498
fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>,
8599
hint: Option<ai::Hint>) -> Result<~[ai::Info], IoError>;
86100
fn timer_init(&mut self) -> Result<~RtioTimer, IoError>;
87-
fn fs_from_raw_fd(&mut self, fd: c_int, close_on_drop: bool) -> ~RtioFileStream;
101+
fn fs_from_raw_fd(&mut self, fd: c_int, close: CloseBehavior) -> ~RtioFileStream;
88102
fn fs_open(&mut self, path: &CString, fm: FileMode, fa: FileAccess)
89103
-> Result<~RtioFileStream, IoError>;
90104
fn fs_unlink(&mut self, path: &CString) -> Result<(), IoError>;

src/libstd/rt/task.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,6 @@ pub extern "C" fn rust_stack_exhausted() {
479479
use rt::in_green_task_context;
480480
use rt::task::Task;
481481
use rt::local::Local;
482-
use rt::logging::Logger;
483482
use unstable::intrinsics;
484483

485484
unsafe {
@@ -529,8 +528,12 @@ pub extern "C" fn rust_stack_exhausted() {
529528
do Local::borrow |task: &mut Task| {
530529
let n = task.name.as_ref().map(|n| n.as_slice()).unwrap_or("<unnamed>");
531530

532-
format_args!(|args| { task.logger.log(args) },
533-
"task '{}' has overflowed its stack", n);
531+
// See the message below for why this is not emitted to the
532+
// task's logger. This has the additional conundrum of the
533+
// logger may not be initialized just yet, meaning that an FFI
534+
// call would happen to initialized it (calling out to libuv),
535+
// and the FFI call needs 2MB of stack when we just ran out.
536+
rterrln!("task '{}' has overflowed its stack", n);
534537
}
535538
} else {
536539
rterrln!("stack overflow in non-task context");

0 commit comments

Comments
 (0)