Skip to content

Commit bcc8d1c

Browse files
committed
---
yaml --- r: 95624 b: refs/heads/dist-snap c: 4eb5336 h: refs/heads/master v: v3
1 parent 7bb1cc6 commit bcc8d1c

File tree

14 files changed

+167
-101
lines changed

14 files changed

+167
-101
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ refs/heads/try: c274a6888410ce3e357e014568b43310ed787d36
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
88
refs/heads/try2: 147ecfdd8221e4a4d4e090486829a06da1e0ca3c
9-
refs/heads/dist-snap: 4ce71eaca34526d0e3ee1ebf0658d2a20d388ef2
9+
refs/heads/dist-snap: 4eb53360541baf3e6df36dc0f0766bc7c1c9f8be
1010
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1111
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503
1212
refs/heads/try3: 9387340aab40a73e8424c48fd42f0c521a4875c0

branches/dist-snap/src/libstd/logging.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ pub fn log(_level: u32, args: &fmt::Arguments) {
112112
}
113113
None => {
114114
// There is no logger anywhere, just write to stderr
115-
let mut logger = StdErrLogger;
115+
let mut logger = StdErrLogger::new();
116116
logger.log(args);
117117
}
118118
}

branches/dist-snap/src/libstd/rt/io/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ pub enum IoErrorKind {
370370
PathAlreadyExists,
371371
PathDoesntExist,
372372
MismatchedFileTypeForOperation,
373+
ResourceUnavailable,
373374
IoUnavailable,
374375
}
375376

@@ -392,6 +393,7 @@ impl ToStr for IoErrorKind {
392393
PathDoesntExist => ~"PathDoesntExist",
393394
MismatchedFileTypeForOperation => ~"MismatchedFileTypeForOperation",
394395
IoUnavailable => ~"IoUnavailable",
396+
ResourceUnavailable => ~"ResourceUnavailable",
395397
}
396398
}
397399
}

branches/dist-snap/src/libstd/rt/io/native/file.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ fn raise_error() {
2121
// XXX: this should probably be a bit more descriptive...
2222
let (kind, desc) = match os::errno() as i32 {
2323
libc::EOF => (EndOfFile, "end of file"),
24+
25+
// These two constants can have the same value on some systems, but
26+
// different values on others, so we can't use a match clause
27+
x if x == libc::EAGAIN || x == libc::EWOULDBLOCK =>
28+
(ResourceUnavailable, "resource temporarily unavailable"),
29+
2430
_ => (OtherIoError, "unknown error"),
2531
};
2632

branches/dist-snap/src/libstd/rt/io/stdio.rs

Lines changed: 44 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,39 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
/*!
12+
13+
This modules provides bindings to the local event loop's TTY interface, using it
14+
to have synchronous, but non-blocking versions of stdio. These handles can be
15+
inspected for information about terminal dimensions or related information
16+
about the stream or terminal that it is attached to.
17+
18+
# Example
19+
20+
```rust
21+
use std::rt::io;
22+
23+
let mut out = io::stdout();
24+
out.write(bytes!("Hello, world!"));
25+
```
26+
27+
*/
28+
1129
use fmt;
1230
use libc;
1331
use option::{Option, Some, None};
1432
use result::{Ok, Err};
1533
use rt::rtio::{IoFactory, RtioTTY, with_local_io};
1634
use super::{Reader, Writer, io_error};
1735

18-
/// Creates a new non-blocking handle to the stdin of the current process.
19-
///
20-
/// See `stdout()` for notes about this function.
21-
pub fn stdin() -> StdReader {
36+
#[fixed_stack_segment] #[inline(never)]
37+
fn tty<T>(fd: libc::c_int, f: &fn(~RtioTTY) -> T) -> T {
2238
do with_local_io |io| {
23-
match io.tty_open(libc::STDIN_FILENO, true, false) {
24-
Ok(tty) => Some(StdReader { inner: tty }),
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)),
2544
Err(e) => {
2645
io_error::cond.raise(e);
2746
None
@@ -30,37 +49,28 @@ pub fn stdin() -> StdReader {
3049
}.unwrap()
3150
}
3251

52+
/// Creates a new non-blocking handle to the stdin of the current process.
53+
///
54+
/// See `stdout()` for notes about this function.
55+
pub fn stdin() -> StdReader {
56+
do tty(libc::STDIN_FILENO) |tty| { StdReader { inner: tty } }
57+
}
58+
3359
/// Creates a new non-blocking handle to the stdout of the current process.
3460
///
3561
/// Note that this is a fairly expensive operation in that at least one memory
3662
/// allocation is performed. Additionally, this must be called from a runtime
3763
/// task context because the stream returned will be a non-blocking object using
3864
/// the local scheduler to perform the I/O.
3965
pub fn stdout() -> StdWriter {
40-
do with_local_io |io| {
41-
match io.tty_open(libc::STDOUT_FILENO, false, false) {
42-
Ok(tty) => Some(StdWriter { inner: tty }),
43-
Err(e) => {
44-
io_error::cond.raise(e);
45-
None
46-
}
47-
}
48-
}.unwrap()
66+
do tty(libc::STDOUT_FILENO) |tty| { StdWriter { inner: tty } }
4967
}
5068

5169
/// Creates a new non-blocking handle to the stderr of the current process.
5270
///
5371
/// See `stdout()` for notes about this function.
5472
pub fn stderr() -> StdWriter {
55-
do with_local_io |io| {
56-
match io.tty_open(libc::STDERR_FILENO, false, false) {
57-
Ok(tty) => Some(StdWriter { inner: tty }),
58-
Err(e) => {
59-
io_error::cond.raise(e);
60-
None
61-
}
62-
}
63-
}.unwrap()
73+
do tty(libc::STDERR_FILENO) |tty| { StdWriter { inner: tty } }
6474
}
6575

6676
/// Prints a string to the stdout of the current process. No newline is emitted
@@ -115,6 +125,11 @@ impl StdReader {
115125
Err(e) => io_error::cond.raise(e),
116126
}
117127
}
128+
129+
/// Returns whether this tream is attached to a TTY instance or not.
130+
///
131+
/// This is similar to libc's isatty() function
132+
pub fn isatty(&self) -> bool { self.inner.isatty() }
118133
}
119134

120135
impl Reader for StdReader {
@@ -170,6 +185,11 @@ impl StdWriter {
170185
Err(e) => io_error::cond.raise(e),
171186
}
172187
}
188+
189+
/// Returns whether this tream is attached to a TTY instance or not.
190+
///
191+
/// This is similar to libc's isatty() function
192+
pub fn isatty(&self) -> bool { self.inner.isatty() }
173193
}
174194

175195
impl Writer for StdWriter {

branches/dist-snap/src/libstd/rt/logging.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use fmt;
1212
use from_str::from_str;
1313
use libc::exit;
1414
use option::{Some, None, Option};
15+
use rt::io;
1516
use rt::crate_map::{ModEntry, CrateMap, iter_crate_map, get_crate_map};
1617
use str::StrSlice;
1718
use u32;
@@ -166,14 +167,23 @@ pub trait Logger {
166167
fn log(&mut self, args: &fmt::Arguments);
167168
}
168169

169-
pub struct StdErrLogger;
170+
/// This logger emits output to the stderr of the process, and contains a lazily
171+
/// initialized event-loop driven handle to the stream.
172+
pub struct StdErrLogger {
173+
priv handle: Option<io::stdio::StdWriter>,
174+
}
175+
176+
impl StdErrLogger {
177+
pub fn new() -> StdErrLogger { StdErrLogger { handle: None } }
178+
}
170179

171180
impl Logger for StdErrLogger {
172181
fn log(&mut self, args: &fmt::Arguments) {
173-
// FIXME(#6846): this should not call the blocking version of println,
174-
// or at least the default loggers for tasks shouldn't do
175-
// that
176-
::rt::util::dumb_println(args);
182+
// First time logging? Get a handle to the stderr of this process.
183+
if self.handle.is_none() {
184+
self.handle = Some(io::stderr());
185+
}
186+
fmt::writeln(self.handle.get_mut_ref() as &mut io::Writer, args);
177187
}
178188
}
179189

branches/dist-snap/src/libstd/rt/rtio.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ pub trait IoFactory {
9797
fn unix_bind(&mut self, path: &CString) ->
9898
Result<~RtioUnixListener, IoError>;
9999
fn unix_connect(&mut self, path: &CString) -> Result<~RtioPipe, IoError>;
100-
fn tty_open(&mut self, fd: c_int, readable: bool, close_on_drop: bool)
100+
fn tty_open(&mut self, fd: c_int, readable: bool)
101101
-> Result<~RtioTTY, IoError>;
102102
}
103103

@@ -182,6 +182,7 @@ pub trait RtioTTY {
182182
fn write(&mut self, buf: &[u8]) -> Result<(), IoError>;
183183
fn set_raw(&mut self, raw: bool) -> Result<(), IoError>;
184184
fn get_winsize(&mut self) -> Result<(int, int), IoError>;
185+
fn isatty(&self) -> bool;
185186
}
186187

187188
pub trait PausibleIdleCallback {

branches/dist-snap/src/libstd/rt/task.rs

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ impl Task {
132132
heap: LocalHeap::new(),
133133
gc: GarbageCollector,
134134
storage: LocalStorage(None),
135-
logger: StdErrLogger,
135+
logger: StdErrLogger::new(),
136136
unwinder: Unwinder { unwinding: false },
137137
taskgroup: None,
138138
death: Death::new(),
@@ -166,7 +166,7 @@ impl Task {
166166
heap: LocalHeap::new(),
167167
gc: GarbageCollector,
168168
storage: LocalStorage(None),
169-
logger: StdErrLogger,
169+
logger: StdErrLogger::new(),
170170
unwinder: Unwinder { unwinding: false },
171171
taskgroup: None,
172172
death: Death::new(),
@@ -188,7 +188,7 @@ impl Task {
188188
heap: LocalHeap::new(),
189189
gc: GarbageCollector,
190190
storage: LocalStorage(None),
191-
logger: StdErrLogger,
191+
logger: StdErrLogger::new(),
192192
unwinder: Unwinder { unwinding: false },
193193
taskgroup: None,
194194
// FIXME(#7544) make watching optional
@@ -549,6 +549,7 @@ pub fn begin_unwind(msg: *c_char, file: *c_char, line: size_t) -> ! {
549549
use rt::logging::Logger;
550550
use str::Str;
551551
use c_str::CString;
552+
use unstable::intrinsics;
552553

553554
unsafe {
554555
let msg = CString::new(msg, false);
@@ -557,35 +558,32 @@ pub fn begin_unwind(msg: *c_char, file: *c_char, line: size_t) -> ! {
557558
Some(s) => s, None => rtabort!("message wasn't utf8?")
558559
};
559560

560-
if in_green_task_context() {
561-
// Be careful not to allocate in this block, if we're failing we may
562-
// have been failing due to a lack of memory in the first place...
563-
do Local::borrow |task: &mut Task| {
564-
let n = task.name.as_ref().map(|n| n.as_slice()).unwrap_or("<unnamed>");
565-
566-
match file.as_str() {
567-
Some(file) => {
568-
format_args!(|args| { task.logger.log(args) },
569-
"task '{}' failed at '{}', {}:{}",
570-
n, msg, file, line);
571-
}
572-
None => {
573-
format_args!(|args| { task.logger.log(args) },
574-
"task '{}' failed at '{}'", n, msg);
575-
}
576-
}
577-
}
578-
} else {
561+
if !in_green_task_context() {
579562
match file.as_str() {
580563
Some(file) => {
581564
rterrln!("failed in non-task context at '{}', {}:{}",
582565
msg, file, line as int);
583566
}
584-
None => rterrln!("failed in non-task context at '{}'", msg),
567+
None => rterrln!("failed in non-task context at '{}'", msg)
585568
}
569+
intrinsics::abort();
586570
}
587571

572+
// Be careful not to allocate in this block, if we're failing we may
573+
// have been failing due to a lack of memory in the first place...
588574
let task: *mut Task = Local::unsafe_borrow();
575+
let n = (*task).name.as_ref().map(|n| n.as_slice()).unwrap_or("<unnamed>");
576+
match file.as_str() {
577+
Some(file) => {
578+
format_args!(|args| { (*task).logger.log(args) },
579+
"task '{}' failed at '{}', {}:{}",
580+
n, msg, file, line);
581+
}
582+
None => {
583+
format_args!(|args| { (*task).logger.log(args) },
584+
"task '{}' failed at '{}'", n, msg);
585+
}
586+
}
589587
if (*task).unwinder.unwinding {
590588
rtabort!("unwinding again");
591589
}

branches/dist-snap/src/libstd/rt/util.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,18 @@ pub fn default_sched_threads() -> uint {
7171

7272
pub fn dumb_println(args: &fmt::Arguments) {
7373
use rt::io::native::stdio::stderr;
74-
use rt::io::Writer;
74+
use rt::io::{Writer, io_error, ResourceUnavailable};
7575
let mut out = stderr();
76-
fmt::writeln(&mut out as &mut Writer, args);
76+
77+
let mut again = true;
78+
do io_error::cond.trap(|e| {
79+
again = e.kind == ResourceUnavailable;
80+
}).inside {
81+
while again {
82+
again = false;
83+
fmt::writeln(&mut out as &mut Writer, args);
84+
}
85+
}
7786
}
7887

7988
pub fn abort(msg: &str) -> ! {

branches/dist-snap/src/libstd/rt/uv/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ pub trait WatcherInterop {
170170
fn get_watcher_data<'r>(&'r mut self) -> &'r mut WatcherData;
171171
fn drop_watcher_data(&mut self);
172172
fn close(self, cb: NullCallback);
173+
fn close_async(self);
173174
}
174175

175176
impl<H, W: Watcher + NativeHandle<*H>> WatcherInterop for W {
@@ -235,6 +236,16 @@ impl<H, W: Watcher + NativeHandle<*H>> WatcherInterop for W {
235236
unsafe { uvll::free_handle(handle as *c_void) }
236237
}
237238
}
239+
240+
fn close_async(self) {
241+
unsafe { uvll::close(self.native_handle(), close_cb); }
242+
243+
extern fn close_cb(handle: *uvll::uv_handle_t) {
244+
let mut h: Handle = NativeHandle::from_native_handle(handle);
245+
h.drop_watcher_data();
246+
unsafe { uvll::free_handle(handle as *c_void) }
247+
}
248+
}
238249
}
239250

240251
// XXX: Need to define the error constants like EOF so they can be

0 commit comments

Comments
 (0)