mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 01:04:03 +00:00
Revert "std: Re-enable at_exit()"
This reverts commit 9e224c2bf1
.
Conflicts:
src/libstd/sys/windows/os.rs
This commit is contained in:
parent
582cba183f
commit
aec67c2ee0
@ -177,7 +177,7 @@ use std::mem;
|
||||
use std::os;
|
||||
use std::rt;
|
||||
use std::slice;
|
||||
use std::sync::{Once, ONCE_INIT, StaticMutex, MUTEX_INIT};
|
||||
use std::sync::{Once, ONCE_INIT};
|
||||
|
||||
use regex::Regex;
|
||||
|
||||
@ -193,8 +193,6 @@ pub const MAX_LOG_LEVEL: u32 = 255;
|
||||
/// The default logging level of a crate if no other is specified.
|
||||
const DEFAULT_LOG_LEVEL: u32 = 1;
|
||||
|
||||
static LOCK: StaticMutex = MUTEX_INIT;
|
||||
|
||||
/// An unsafe constant that is the maximum logging level of any module
|
||||
/// specified. This is the first line of defense to determining whether a
|
||||
/// logging statement should be run.
|
||||
@ -281,18 +279,9 @@ impl Drop for DefaultLogger {
|
||||
pub fn log(level: u32, loc: &'static LogLocation, args: fmt::Arguments) {
|
||||
// Test the literal string from args against the current filter, if there
|
||||
// is one.
|
||||
unsafe {
|
||||
let _g = LOCK.lock();
|
||||
match FILTER as uint {
|
||||
0 => {}
|
||||
1 => panic!("cannot log after main thread has exited"),
|
||||
n => {
|
||||
let filter = mem::transmute::<_, &Regex>(n);
|
||||
if !filter.is_match(args.to_string().as_slice()) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
match unsafe { FILTER.as_ref() } {
|
||||
Some(filter) if !filter.is_match(args.to_string()[]) => return,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// Completely remove the local logger from TLS in case anyone attempts to
|
||||
@ -374,15 +363,9 @@ pub fn mod_enabled(level: u32, module: &str) -> bool {
|
||||
|
||||
// This assertion should never get tripped unless we're in an at_exit
|
||||
// handler after logging has been torn down and a logging attempt was made.
|
||||
assert!(unsafe { !DIRECTIVES.is_null() });
|
||||
|
||||
let _g = LOCK.lock();
|
||||
unsafe {
|
||||
assert!(DIRECTIVES as uint != 0);
|
||||
assert!(DIRECTIVES as uint != 1,
|
||||
"cannot log after the main thread has exited");
|
||||
|
||||
enabled(level, module, (*DIRECTIVES).iter())
|
||||
}
|
||||
enabled(level, module, unsafe { (*DIRECTIVES).iter() })
|
||||
}
|
||||
|
||||
fn enabled(level: u32,
|
||||
@ -438,15 +421,14 @@ fn init() {
|
||||
|
||||
// Schedule the cleanup for the globals for when the runtime exits.
|
||||
rt::at_exit(move |:| {
|
||||
let _g = LOCK.lock();
|
||||
assert!(!DIRECTIVES.is_null());
|
||||
let _directives: Box<Vec<directive::LogDirective>> =
|
||||
mem::transmute(DIRECTIVES);
|
||||
DIRECTIVES = 1 as *const Vec<directive::LogDirective>;
|
||||
DIRECTIVES = 0 as *const Vec<directive::LogDirective>;
|
||||
|
||||
if !FILTER.is_null() {
|
||||
let _filter: Box<Regex> = mem::transmute(FILTER);
|
||||
FILTER = 1 as *const _;
|
||||
FILTER = 0 as *const _;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -26,19 +26,29 @@
|
||||
//! ```
|
||||
|
||||
use self::StdSource::*;
|
||||
use prelude::*;
|
||||
|
||||
use boxed::Box;
|
||||
use cell::RefCell;
|
||||
use clone::Clone;
|
||||
use failure::LOCAL_STDERR;
|
||||
use fmt;
|
||||
use io::{IoResult, IoError, OtherIoError};
|
||||
use io::{standard_error, EndOfFile, LineBufferedWriter, BufferedReader};
|
||||
use io::{Reader, Writer, IoResult, IoError, OtherIoError, Buffer,
|
||||
standard_error, EndOfFile, LineBufferedWriter, BufferedReader};
|
||||
use kinds::{Sync, Send};
|
||||
use libc;
|
||||
use mem;
|
||||
use option::Option;
|
||||
use option::Option::{Some, None};
|
||||
use ops::{Deref, DerefMut, FnOnce};
|
||||
use result::Result::{Ok, Err};
|
||||
use rt;
|
||||
use slice::SliceExt;
|
||||
use str::StrExt;
|
||||
use string::String;
|
||||
use sys::{fs, tty};
|
||||
use sync::{Arc, Mutex, MutexGuard, StaticMutex, MUTEX_INIT};
|
||||
use sync::{Arc, Mutex, MutexGuard, Once, ONCE_INIT};
|
||||
use uint;
|
||||
use vec::Vec;
|
||||
|
||||
// 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
|
||||
@ -205,15 +215,14 @@ impl Reader for StdinReader {
|
||||
pub fn stdin() -> StdinReader {
|
||||
// We're following the same strategy as kimundi's lazy_static library
|
||||
static mut STDIN: *const StdinReader = 0 as *const StdinReader;
|
||||
static LOCK: StaticMutex = MUTEX_INIT;
|
||||
static ONCE: Once = ONCE_INIT;
|
||||
|
||||
unsafe {
|
||||
let _g = LOCK.lock();
|
||||
if STDIN as uint == 0 {
|
||||
// The default buffer capacity is 64k, but apparently windows
|
||||
// doesn't like 64k reads on stdin. See #13304 for details, but the
|
||||
// idea is that on windows we use a slightly smaller buffer that's
|
||||
// been seen to be acceptable.
|
||||
ONCE.doit(|| {
|
||||
// The default buffer capacity is 64k, but apparently windows doesn't like
|
||||
// 64k reads on stdin. See #13304 for details, but the idea is that on
|
||||
// windows we use a slightly smaller buffer that's been seen to be
|
||||
// acceptable.
|
||||
let stdin = if cfg!(windows) {
|
||||
BufferedReader::with_capacity(8 * 1024, stdin_raw())
|
||||
} else {
|
||||
@ -226,15 +235,11 @@ pub fn stdin() -> StdinReader {
|
||||
|
||||
// Make sure to free it at exit
|
||||
rt::at_exit(|| {
|
||||
let g = LOCK.lock();
|
||||
let stdin = STDIN;
|
||||
STDIN = 1 as *const _;
|
||||
drop(g);
|
||||
mem::transmute::<_, Box<StdinReader>>(stdin);
|
||||
mem::transmute::<_, Box<StdinReader>>(STDIN);
|
||||
STDIN = 0 as *const _;
|
||||
});
|
||||
} else if STDIN as uint == 1 {
|
||||
panic!("accessing stdin after the main thread has exited")
|
||||
}
|
||||
});
|
||||
|
||||
(*STDIN).clone()
|
||||
}
|
||||
}
|
||||
|
@ -229,13 +229,13 @@ pub mod thread;
|
||||
pub mod sync;
|
||||
pub mod comm;
|
||||
|
||||
#[path = "sys/common/mod.rs"] mod sys_common;
|
||||
|
||||
#[cfg(unix)]
|
||||
#[path = "sys/unix/mod.rs"] mod sys;
|
||||
#[cfg(windows)]
|
||||
#[path = "sys/windows/mod.rs"] mod sys;
|
||||
|
||||
#[path = "sys/common/mod.rs"] mod sys_common;
|
||||
|
||||
pub mod rt;
|
||||
mod failure;
|
||||
|
||||
|
@ -29,8 +29,6 @@ type Queue = Vec<Thunk>;
|
||||
static LOCK: Mutex = MUTEX_INIT;
|
||||
static mut QUEUE: *mut Queue = 0 as *mut Queue;
|
||||
|
||||
const DTOR_RUN_ITERS: uint = 10;
|
||||
|
||||
unsafe fn init() {
|
||||
if QUEUE.is_null() {
|
||||
let state: Box<Queue> = box Vec::new();
|
||||
@ -51,7 +49,7 @@ pub fn cleanup() {
|
||||
unsafe {
|
||||
LOCK.lock();
|
||||
let queue = QUEUE;
|
||||
QUEUE = 1u as *mut _;
|
||||
QUEUE = 1 as *mut _;
|
||||
LOCK.unlock();
|
||||
|
||||
// make sure we're not recursively cleaning up
|
||||
|
@ -92,7 +92,9 @@ fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int {
|
||||
// but we just do this to name the main thread and to give it correct
|
||||
// info about the stack bounds.
|
||||
let thread: Thread = NewThread::new(Some("<main>".to_string()));
|
||||
thread_info::set(sys::thread::guard::main(), thread);
|
||||
thread_info::set((my_stack_bottom, my_stack_top),
|
||||
sys::thread::guard::main(),
|
||||
thread);
|
||||
|
||||
// By default, some platforms will send a *signal* when a EPIPE error
|
||||
// would otherwise be delivered. This runtime doesn't install a SIGPIPE
|
||||
@ -131,14 +133,20 @@ fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int {
|
||||
}
|
||||
}
|
||||
|
||||
/// Enqueues a procedure to run when the main thread exits.
|
||||
/// Enqueues a procedure to run when the runtime is cleaned up
|
||||
///
|
||||
/// The procedure passed to this function will be executed as part of the
|
||||
/// runtime cleanup phase. For normal rust programs, this means that it will run
|
||||
/// after all other threads have exited.
|
||||
///
|
||||
/// The procedure is *not* executed with a local `Thread` available to it, so
|
||||
/// primitives like logging, I/O, channels, spawning, etc, are *not* available.
|
||||
/// This is meant for "bare bones" usage to clean up runtime details, this is
|
||||
/// not meant as a general-purpose "let's clean everything up" function.
|
||||
///
|
||||
/// It is forbidden for procedures to register more `at_exit` handlers when they
|
||||
/// are running, and doing so will lead to a process abort.
|
||||
///
|
||||
/// Note that other threads may still be running when `at_exit` routines start
|
||||
/// running.
|
||||
pub fn at_exit<F: FnOnce() + Send>(f: F) {
|
||||
pub fn at_exit<F:FnOnce()+Send>(f: F) {
|
||||
at_exit_imp::push(Thunk::new(f));
|
||||
}
|
||||
|
||||
@ -154,5 +162,8 @@ pub fn at_exit<F: FnOnce() + Send>(f: F) {
|
||||
pub unsafe fn cleanup() {
|
||||
args::cleanup();
|
||||
sys::stack_overflow::cleanup();
|
||||
at_exit_imp::cleanup();
|
||||
// FIXME: (#20012): the resources being cleaned up by at_exit
|
||||
// currently are not prepared for cleanup to happen asynchronously
|
||||
// with detached threads using the resources; for now, we leak.
|
||||
// at_exit_imp::cleanup();
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ use intrinsics;
|
||||
use libc::c_void;
|
||||
use mem;
|
||||
use sync::atomic;
|
||||
use sys_common::mutex::{Mutex, MUTEX_INIT};
|
||||
use sync::{Once, ONCE_INIT};
|
||||
|
||||
use rt::libunwind as uw;
|
||||
|
||||
@ -540,20 +540,11 @@ pub fn begin_unwind<M: Any + Send>(msg: M, file_line: &(&'static str, uint)) ->
|
||||
/// Doing this split took the LLVM IR line counts of `fn main() { panic!()
|
||||
/// }` from ~1900/3700 (-O/no opts) to 180/590.
|
||||
#[inline(never)] #[cold] // this is the slow path, please never inline this
|
||||
fn begin_unwind_inner(msg: Box<Any + Send>,
|
||||
file_line: &(&'static str, uint)) -> ! {
|
||||
fn begin_unwind_inner(msg: Box<Any + Send>, file_line: &(&'static str, uint)) -> ! {
|
||||
// Make sure the default failure handler is registered before we look at the
|
||||
// callbacks.
|
||||
unsafe {
|
||||
static LOCK: Mutex = MUTEX_INIT;
|
||||
static mut INIT: bool = false;
|
||||
LOCK.lock();
|
||||
if !INIT {
|
||||
register(failure::on_fail);
|
||||
INIT = true;
|
||||
}
|
||||
LOCK.unlock();
|
||||
}
|
||||
static INIT: Once = ONCE_INIT;
|
||||
INIT.doit(|| unsafe { register(failure::on_fail); });
|
||||
|
||||
// First, invoke call the user-defined callbacks triggered on thread panic.
|
||||
//
|
||||
|
@ -20,8 +20,6 @@
|
||||
//! can be created in the future and there must be no active timers at that
|
||||
//! time.
|
||||
|
||||
#![macro_escape]
|
||||
|
||||
use prelude::*;
|
||||
|
||||
use cell::UnsafeCell;
|
||||
@ -70,17 +68,6 @@ struct RaceBox(helper_signal::signal);
|
||||
unsafe impl Send for RaceBox {}
|
||||
unsafe impl Sync for RaceBox {}
|
||||
|
||||
macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => (
|
||||
static $name: Helper<$m> = Helper {
|
||||
lock: ::sync::MUTEX_INIT,
|
||||
cond: ::sync::CONDVAR_INIT,
|
||||
chan: ::cell::UnsafeCell { value: 0 as *mut Sender<$m> },
|
||||
signal: ::cell::UnsafeCell { value: 0 },
|
||||
initialized: ::cell::UnsafeCell { value: false },
|
||||
shutdown: ::cell::UnsafeCell { value: false },
|
||||
};
|
||||
) }
|
||||
|
||||
impl<M: Send> Helper<M> {
|
||||
/// Lazily boots a helper thread, becoming a no-op if the helper has already
|
||||
/// been spawned.
|
||||
@ -97,7 +84,7 @@ impl<M: Send> Helper<M> {
|
||||
{
|
||||
unsafe {
|
||||
let _guard = self.lock.lock().unwrap();
|
||||
if *self.chan.get() as uint == 0 {
|
||||
if !*self.initialized.get() {
|
||||
let (tx, rx) = channel();
|
||||
*self.chan.get() = mem::transmute(box tx);
|
||||
let (receive, send) = helper_signal::new();
|
||||
@ -106,17 +93,15 @@ impl<M: Send> Helper<M> {
|
||||
let receive = RaceBox(receive);
|
||||
|
||||
let t = f();
|
||||
Thread::spawn(move || {
|
||||
Thread::spawn(move |:| {
|
||||
helper(receive.0, rx, t);
|
||||
let _g = self.lock.lock().unwrap();
|
||||
*self.shutdown.get() = true;
|
||||
self.cond.notify_one()
|
||||
}).detach();
|
||||
|
||||
rt::at_exit(move || { self.shutdown() });
|
||||
rt::at_exit(move|:| { self.shutdown() });
|
||||
*self.initialized.get() = true;
|
||||
} else if *self.chan.get() as uint == 1 {
|
||||
panic!("cannot continue usage after shutdown");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -131,9 +116,7 @@ impl<M: Send> Helper<M> {
|
||||
// Must send and *then* signal to ensure that the child receives the
|
||||
// message. Otherwise it could wake up and go to sleep before we
|
||||
// send the message.
|
||||
assert!(*self.chan.get() as uint != 0);
|
||||
assert!(*self.chan.get() as uint != 1,
|
||||
"cannot continue usage after shutdown");
|
||||
assert!(!self.chan.get().is_null());
|
||||
(**self.chan.get()).send(msg);
|
||||
helper_signal::signal(*self.signal.get() as helper_signal::signal);
|
||||
}
|
||||
@ -146,13 +129,9 @@ impl<M: Send> Helper<M> {
|
||||
// returns.
|
||||
let mut guard = self.lock.lock().unwrap();
|
||||
|
||||
let ptr = *self.chan.get();
|
||||
if ptr as uint == 1 {
|
||||
panic!("cannot continue usage after shutdown");
|
||||
}
|
||||
// Close the channel by destroying it
|
||||
let chan: Box<Sender<M>> = mem::transmute(*self.chan.get());
|
||||
*self.chan.get() = 1 as *mut Sender<M>;
|
||||
*self.chan.get() = 0 as *mut Sender<M>;
|
||||
drop(chan);
|
||||
helper_signal::signal(*self.signal.get() as helper_signal::signal);
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(missing_docs)]
|
||||
#![macro_escape]
|
||||
#![allow(dead_code)]
|
||||
|
||||
use io::{mod, IoError, IoResult};
|
||||
use prelude::*;
|
||||
|
@ -29,7 +29,6 @@ impl Mutex {
|
||||
/// Behavior is undefined if the mutex is moved after the first method is
|
||||
/// called on the mutex.
|
||||
#[inline]
|
||||
#[allow(dead_code)] // sys is not exported yet
|
||||
pub unsafe fn new() -> Mutex { Mutex(imp::Mutex::new()) }
|
||||
|
||||
/// Lock the mutex blocking the current thread until it is available.
|
||||
|
@ -23,9 +23,7 @@ use io::{IoResult, IoError};
|
||||
use sys::{mod, retry, c, sock_t, last_error, last_net_error, last_gai_error, close_sock,
|
||||
wrlen, msglen_t, os, wouldblock, set_nonblocking, timer, ms_to_timeval,
|
||||
decode_error_detailed};
|
||||
use sync::Mutex;
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
use sync::MutexGuard;
|
||||
use sync::{Mutex, MutexGuard};
|
||||
use sys_common::{mod, keep_going, short_write, timeout};
|
||||
use prelude::*;
|
||||
use cmp;
|
||||
@ -613,13 +611,11 @@ impl Drop for Inner {
|
||||
fn drop(&mut self) { unsafe { close_sock(self.fd); } }
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
pub struct Guard<'a> {
|
||||
pub fd: sock_t,
|
||||
pub guard: MutexGuard<'a, ()>,
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
#[unsafe_destructor]
|
||||
impl<'a> Drop for Guard<'a> {
|
||||
fn drop(&mut self) {
|
||||
|
@ -26,7 +26,6 @@ impl RWLock {
|
||||
/// Usage of an RWLock is undefined if it is moved after its first use (any
|
||||
/// function calls below).
|
||||
#[inline]
|
||||
#[allow(dead_code)] // sys is not exported yet
|
||||
pub unsafe fn new() -> RWLock { RWLock(imp::RWLock::new()) }
|
||||
|
||||
/// Acquire shared access to the underlying lock, blocking the current
|
||||
|
@ -121,6 +121,37 @@ pub unsafe fn record_os_managed_stack_bounds(stack_lo: uint, _stack_hi: uint) {
|
||||
record_sp_limit(stack_lo + RED_ZONE);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn record_rust_managed_stack_bounds(stack_lo: uint, stack_hi: uint) {
|
||||
// When the old runtime had segmented stacks, it used a calculation that was
|
||||
// "limit + RED_ZONE + FUDGE". The red zone was for things like dynamic
|
||||
// symbol resolution, llvm function calls, etc. In theory this red zone
|
||||
// value is 0, but it matters far less when we have gigantic stacks because
|
||||
// we don't need to be so exact about our stack budget. The "fudge factor"
|
||||
// was because LLVM doesn't emit a stack check for functions < 256 bytes in
|
||||
// size. Again though, we have giant stacks, so we round all these
|
||||
// calculations up to the nice round number of 20k.
|
||||
record_sp_limit(stack_lo + RED_ZONE);
|
||||
|
||||
return target_record_stack_bounds(stack_lo, stack_hi);
|
||||
|
||||
#[cfg(not(windows))] #[inline(always)]
|
||||
unsafe fn target_record_stack_bounds(_stack_lo: uint, _stack_hi: uint) {}
|
||||
|
||||
#[cfg(all(windows, target_arch = "x86"))] #[inline(always)]
|
||||
unsafe fn target_record_stack_bounds(stack_lo: uint, stack_hi: uint) {
|
||||
// stack range is at TIB: %fs:0x04 (top) and %fs:0x08 (bottom)
|
||||
asm!("mov $0, %fs:0x04" :: "r"(stack_hi) :: "volatile");
|
||||
asm!("mov $0, %fs:0x08" :: "r"(stack_lo) :: "volatile");
|
||||
}
|
||||
#[cfg(all(windows, target_arch = "x86_64"))] #[inline(always)]
|
||||
unsafe fn target_record_stack_bounds(stack_lo: uint, stack_hi: uint) {
|
||||
// stack range is at TIB: %gs:0x08 (top) and %gs:0x10 (bottom)
|
||||
asm!("mov $0, %gs:0x08" :: "r"(stack_hi) :: "volatile");
|
||||
asm!("mov $0, %gs:0x10" :: "r"(stack_lo) :: "volatile");
|
||||
}
|
||||
}
|
||||
|
||||
/// Records the current limit of the stack as specified by `end`.
|
||||
///
|
||||
/// This is stored in an OS-dependent location, likely inside of the thread
|
||||
|
@ -8,8 +8,6 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(dead_code)] // stack_guard isn't used right now on all platforms
|
||||
|
||||
use core::prelude::*;
|
||||
|
||||
use thread::Thread;
|
||||
@ -17,6 +15,10 @@ use cell::RefCell;
|
||||
use string::String;
|
||||
|
||||
struct ThreadInfo {
|
||||
// This field holds the known bounds of the stack in (lo, hi)
|
||||
// form. Not all threads necessarily know their precise bounds,
|
||||
// hence this is optional.
|
||||
stack_bounds: (uint, uint),
|
||||
stack_guard: uint,
|
||||
thread: Thread,
|
||||
}
|
||||
@ -33,6 +35,7 @@ impl ThreadInfo {
|
||||
THREAD_INFO.with(|c| {
|
||||
if c.borrow().is_none() {
|
||||
*c.borrow_mut() = Some(ThreadInfo {
|
||||
stack_bounds: (0, 0),
|
||||
stack_guard: 0,
|
||||
thread: NewThread::new(None),
|
||||
})
|
||||
@ -50,9 +53,10 @@ pub fn stack_guard() -> uint {
|
||||
ThreadInfo::with(|info| info.stack_guard)
|
||||
}
|
||||
|
||||
pub fn set(stack_guard: uint, thread: Thread) {
|
||||
pub fn set(stack_bounds: (uint, uint), stack_guard: uint, thread: Thread) {
|
||||
THREAD_INFO.with(|c| assert!(c.borrow().is_none()));
|
||||
THREAD_INFO.with(move |c| *c.borrow_mut() = Some(ThreadInfo{
|
||||
stack_bounds: stack_bounds,
|
||||
stack_guard: stack_guard,
|
||||
thread: thread,
|
||||
}));
|
||||
|
@ -55,11 +55,11 @@
|
||||
//! ```
|
||||
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(dead_code)] // sys isn't exported yet
|
||||
|
||||
use prelude::*;
|
||||
|
||||
use sync::atomic::{mod, AtomicUint};
|
||||
use sync::{Mutex, Once, ONCE_INIT};
|
||||
|
||||
use sys::thread_local as imp;
|
||||
|
||||
@ -140,6 +140,9 @@ pub const INIT_INNER: StaticKeyInner = StaticKeyInner {
|
||||
key: atomic::INIT_ATOMIC_UINT,
|
||||
};
|
||||
|
||||
static INIT_KEYS: Once = ONCE_INIT;
|
||||
static mut KEYS: *mut Mutex<Vec<imp::Key>> = 0 as *mut _;
|
||||
|
||||
impl StaticKey {
|
||||
/// Gets the value associated with this TLS key
|
||||
///
|
||||
|
@ -83,12 +83,12 @@
|
||||
/// to symbols. This is a bit of a hokey implementation as-is, but it works for
|
||||
/// all unix platforms we support right now, so it at least gets the job done.
|
||||
|
||||
use prelude::*;
|
||||
|
||||
use c_str::CString;
|
||||
use io::IoResult;
|
||||
use io::{IoResult, Writer};
|
||||
use libc;
|
||||
use mem;
|
||||
use option::Option::{mod, Some, None};
|
||||
use result::Result::{Ok, Err};
|
||||
use sync::{StaticMutex, MUTEX_INIT};
|
||||
|
||||
use sys_common::backtrace::*;
|
||||
@ -151,7 +151,7 @@ pub fn write(w: &mut Writer) -> IoResult<()> {
|
||||
// I/O done here is blocking I/O, not green I/O, so we don't have to
|
||||
// worry about this being a native vs green mutex.
|
||||
static LOCK: StaticMutex = MUTEX_INIT;
|
||||
let _g = LOCK.lock();
|
||||
let _g = unsafe { LOCK.lock() };
|
||||
|
||||
try!(writeln!(w, "stack backtrace:"));
|
||||
|
||||
@ -241,8 +241,12 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> {
|
||||
|
||||
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
|
||||
fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> {
|
||||
use iter::{Iterator, IteratorExt};
|
||||
use os;
|
||||
use path::GenericPath;
|
||||
use ptr::PtrExt;
|
||||
use ptr;
|
||||
use slice::SliceExt;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// libbacktrace.h API
|
||||
|
@ -10,14 +10,30 @@
|
||||
|
||||
#![allow(missing_docs)]
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(unused_imports)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(unused_unsafe)]
|
||||
#![allow(unused_mut)]
|
||||
|
||||
extern crate libc;
|
||||
|
||||
use num;
|
||||
use num::{Int, SignedInt};
|
||||
use prelude::*;
|
||||
use io::{mod, IoResult, IoError};
|
||||
use sys_common::mkerr_libc;
|
||||
|
||||
macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => (
|
||||
static $name: Helper<$m> = Helper {
|
||||
lock: ::sync::MUTEX_INIT,
|
||||
cond: ::sync::CONDVAR_INIT,
|
||||
chan: ::cell::UnsafeCell { value: 0 as *mut Sender<$m> },
|
||||
signal: ::cell::UnsafeCell { value: 0 },
|
||||
initialized: ::cell::UnsafeCell { value: false },
|
||||
shutdown: ::cell::UnsafeCell { value: false },
|
||||
};
|
||||
) }
|
||||
|
||||
pub mod backtrace;
|
||||
pub mod c;
|
||||
pub mod ext;
|
||||
|
@ -11,6 +11,7 @@
|
||||
use cell::UnsafeCell;
|
||||
use kinds::Sync;
|
||||
use sys::sync as ffi;
|
||||
use sys_common::mutex;
|
||||
|
||||
pub struct Mutex { inner: UnsafeCell<ffi::pthread_mutex_t> }
|
||||
|
||||
@ -25,7 +26,6 @@ pub const MUTEX_INIT: Mutex = Mutex {
|
||||
|
||||
unsafe impl Sync for Mutex {}
|
||||
|
||||
#[allow(dead_code)] // sys isn't exported yet
|
||||
impl Mutex {
|
||||
#[inline]
|
||||
pub unsafe fn new() -> Mutex {
|
||||
|
@ -10,16 +10,17 @@
|
||||
|
||||
//! Implementation of `std::os` functionality for unix systems
|
||||
|
||||
#![allow(unused_imports)] // lots of cfg code here
|
||||
|
||||
use prelude::*;
|
||||
|
||||
use error::{FromError, Error};
|
||||
use fmt;
|
||||
use io::{IoError, IoResult};
|
||||
use libc::{mod, c_int, c_char};
|
||||
use os;
|
||||
use libc::{mod, c_int, c_char, c_void};
|
||||
use path::BytesContainer;
|
||||
use ptr;
|
||||
use sync::atomic::{AtomicInt, INIT_ATOMIC_INT, SeqCst};
|
||||
use sys::fs::FileDesc;
|
||||
use os;
|
||||
|
||||
use os::TMPBUF_SZ;
|
||||
|
||||
|
@ -145,7 +145,7 @@ impl UnixStream {
|
||||
fn lock_nonblocking<'a>(&'a self) -> Guard<'a> {
|
||||
let ret = Guard {
|
||||
fd: self.fd(),
|
||||
guard: self.inner.lock.lock().unwrap(),
|
||||
guard: unsafe { self.inner.lock.lock().unwrap() },
|
||||
};
|
||||
assert!(set_nonblocking(self.fd(), true).is_ok());
|
||||
ret
|
||||
|
@ -11,7 +11,7 @@ use self::Req::*;
|
||||
|
||||
use libc::{mod, pid_t, c_void, c_int};
|
||||
use c_str::CString;
|
||||
use io::{IoResult, EndOfFile};
|
||||
use io::{mod, IoResult, IoError, EndOfFile};
|
||||
use mem;
|
||||
use os;
|
||||
use ptr;
|
||||
@ -327,7 +327,7 @@ impl Process {
|
||||
// The actual communication between the helper thread and this thread is
|
||||
// quite simple, just a channel moving data around.
|
||||
|
||||
HELPER.boot(register_sigchld, waitpid_helper);
|
||||
unsafe { HELPER.boot(register_sigchld, waitpid_helper) }
|
||||
|
||||
match self.try_wait() {
|
||||
Some(ret) => return Ok(ret),
|
||||
@ -335,7 +335,7 @@ impl Process {
|
||||
}
|
||||
|
||||
let (tx, rx) = channel();
|
||||
HELPER.send(NewChild(self.pid, tx, deadline));
|
||||
unsafe { HELPER.send(NewChild(self.pid, tx, deadline)); }
|
||||
return match rx.recv_opt() {
|
||||
Ok(e) => Ok(e),
|
||||
Err(()) => Err(timeout("wait timed out")),
|
||||
@ -419,15 +419,8 @@ impl Process {
|
||||
Ok(NewChild(pid, tx, deadline)) => {
|
||||
active.push((pid, tx, deadline));
|
||||
}
|
||||
// Once we've been disconnected it means the main
|
||||
// thread is exiting (at_exit has run). We could
|
||||
// still have active waiter for other threads, so
|
||||
// we're just going to drop them all on the floor.
|
||||
// This means that they won't receive a "you're
|
||||
// done" message in which case they'll be considered
|
||||
// as timed out, but more generally errors will
|
||||
// start propagating.
|
||||
Err(comm::Disconnected) => {
|
||||
assert!(active.len() == 0);
|
||||
break 'outer;
|
||||
}
|
||||
Err(comm::Empty) => break,
|
||||
|
@ -17,7 +17,6 @@ pub const RWLOCK_INIT: RWLock = RWLock {
|
||||
inner: UnsafeCell { value: ffi::PTHREAD_RWLOCK_INITIALIZER },
|
||||
};
|
||||
|
||||
#[allow(dead_code)] // sys isn't exported yet
|
||||
impl RWLock {
|
||||
#[inline]
|
||||
pub unsafe fn new() -> RWLock {
|
||||
|
@ -34,6 +34,7 @@ impl Drop for Handler {
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||
mod imp {
|
||||
use core::prelude::*;
|
||||
use sys_common::stack;
|
||||
|
||||
use super::Handler;
|
||||
|
@ -135,6 +135,10 @@ impl TcpAcceptor {
|
||||
Err(sys_common::eof())
|
||||
}
|
||||
|
||||
pub fn socket_name(&mut self) -> IoResult<ip::SocketAddr> {
|
||||
net::sockname(self.fd(), libc::getsockname)
|
||||
}
|
||||
|
||||
pub fn set_timeout(&mut self, timeout: Option<u64>) {
|
||||
self.deadline = timeout.map(|a| sys::timer::now() + a).unwrap_or(0);
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ pub fn now() -> u64 {
|
||||
fn helper(input: libc::c_int, messages: Receiver<Req>, _: ()) {
|
||||
let mut set: c::fd_set = unsafe { mem::zeroed() };
|
||||
|
||||
let fd = FileDesc::new(input, true);
|
||||
let mut fd = FileDesc::new(input, true);
|
||||
let mut timeout: libc::timeval = unsafe { mem::zeroed() };
|
||||
|
||||
// active timers are those which are able to be selected upon (and it's a
|
||||
@ -168,15 +168,8 @@ fn helper(input: libc::c_int, messages: Receiver<Req>, _: ()) {
|
||||
1 => {
|
||||
loop {
|
||||
match messages.try_recv() {
|
||||
// Once we've been disconnected it means the main thread
|
||||
// is exiting (at_exit has run). We could still have
|
||||
// active timers for other threads, so we're just going
|
||||
// to drop them all on the floor. This is all we can
|
||||
// really do, however, to prevent resource leakage. The
|
||||
// remaining timers will likely start panicking quickly
|
||||
// as they attempt to re-use this thread but are
|
||||
// disallowed to do so.
|
||||
Err(comm::Disconnected) => {
|
||||
assert!(active.len() == 0);
|
||||
break 'outer;
|
||||
}
|
||||
|
||||
|
@ -43,4 +43,5 @@ impl TTY {
|
||||
pub fn get_winsize(&mut self) -> IoResult<(int, int)> {
|
||||
Err(sys_common::unimpl())
|
||||
}
|
||||
pub fn isatty(&self) -> bool { false }
|
||||
}
|
||||
|
@ -7,22 +7,19 @@
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! As always, windows has something very different than unix, we mainly want
|
||||
//! to avoid having to depend too much on libunwind for windows.
|
||||
//!
|
||||
//! If you google around, you'll find a fair bit of references to built-in
|
||||
//! functions to get backtraces on windows. It turns out that most of these are
|
||||
//! in an external library called dbghelp. I was unable to find this library
|
||||
//! via `-ldbghelp`, but it is apparently normal to do the `dlopen` equivalent
|
||||
//! of it.
|
||||
//!
|
||||
//! You'll also find that there's a function called CaptureStackBackTrace
|
||||
//! mentioned frequently (which is also easy to use), but sadly I didn't have a
|
||||
//! copy of that function in my mingw install (maybe it was broken?). Instead,
|
||||
//! this takes the route of using StackWalk64 in order to walk the stack.
|
||||
|
||||
#![allow(dead_code)] // constants/fields aren't always used on all platforms
|
||||
/// As always, windows has something very different than unix, we mainly want
|
||||
/// to avoid having to depend too much on libunwind for windows.
|
||||
///
|
||||
/// If you google around, you'll find a fair bit of references to built-in
|
||||
/// functions to get backtraces on windows. It turns out that most of these are
|
||||
/// in an external library called dbghelp. I was unable to find this library
|
||||
/// via `-ldbghelp`, but it is apparently normal to do the `dlopen` equivalent
|
||||
/// of it.
|
||||
///
|
||||
/// You'll also find that there's a function called CaptureStackBackTrace
|
||||
/// mentioned frequently (which is also easy to use), but sadly I didn't have a
|
||||
/// copy of that function in my mingw install (maybe it was broken?). Instead,
|
||||
/// this takes the route of using StackWalk64 in order to walk the stack.
|
||||
|
||||
use c_str::CString;
|
||||
use intrinsics;
|
||||
@ -297,7 +294,7 @@ pub fn write(w: &mut Writer) -> IoResult<()> {
|
||||
// According to windows documentation, all dbghelp functions are
|
||||
// single-threaded.
|
||||
static LOCK: StaticMutex = MUTEX_INIT;
|
||||
let _g = LOCK.lock();
|
||||
let _g = unsafe { LOCK.lock() };
|
||||
|
||||
// Open up dbghelp.dll, we don't link to it explicitly because it can't
|
||||
// always be found. Additionally, it's nice having fewer dependencies.
|
||||
|
@ -15,6 +15,7 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
use libc;
|
||||
use prelude::*;
|
||||
|
||||
pub const WSADESCRIPTION_LEN: uint = 256;
|
||||
pub const WSASYS_STATUS_LEN: uint = 128;
|
||||
|
@ -10,17 +10,21 @@
|
||||
|
||||
//! Blocking Windows-based file I/O
|
||||
|
||||
use alloc::arc::Arc;
|
||||
use libc::{mod, c_int};
|
||||
|
||||
use io;
|
||||
use c_str::CString;
|
||||
use mem;
|
||||
use ptr;
|
||||
use sys::os::fill_utf16_buf_and_decode;
|
||||
use path;
|
||||
use ptr;
|
||||
use str;
|
||||
use io;
|
||||
|
||||
use prelude::*;
|
||||
use sys;
|
||||
use sys::os;
|
||||
use sys_common::{unimpl, mkerr_libc};
|
||||
use sys_common::{keep_going, eof, mkerr_libc};
|
||||
|
||||
use io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode};
|
||||
use io::{IoResult, IoError, FileStat, SeekStyle};
|
||||
@ -441,7 +445,7 @@ pub fn stat(p: &Path) -> IoResult<FileStat> {
|
||||
// FIXME: move this to platform-specific modules (for now)?
|
||||
pub fn lstat(_p: &Path) -> IoResult<FileStat> {
|
||||
// FIXME: implementation is missing
|
||||
Err(unimpl())
|
||||
Err(super::unimpl())
|
||||
}
|
||||
|
||||
pub fn utime(p: &Path, atime: u64, mtime: u64) -> IoResult<()> {
|
||||
|
@ -11,14 +11,30 @@
|
||||
#![allow(missing_docs)]
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(non_snake_case)]
|
||||
#![allow(unused_imports)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(unused_unsafe)]
|
||||
#![allow(unused_mut)]
|
||||
|
||||
extern crate libc;
|
||||
|
||||
use num;
|
||||
use mem;
|
||||
use prelude::*;
|
||||
use io::{mod, IoResult, IoError};
|
||||
use sync::{Once, ONCE_INIT};
|
||||
|
||||
macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => (
|
||||
static $name: Helper<$m> = Helper {
|
||||
lock: ::sync::MUTEX_INIT,
|
||||
cond: ::sync::CONDVAR_INIT,
|
||||
chan: ::cell::UnsafeCell { value: 0 as *mut Sender<$m> },
|
||||
signal: ::cell::UnsafeCell { value: 0 },
|
||||
initialized: ::cell::UnsafeCell { value: false },
|
||||
shutdown: ::cell::UnsafeCell { value: false },
|
||||
};
|
||||
) }
|
||||
|
||||
pub mod backtrace;
|
||||
pub mod c;
|
||||
pub mod ext;
|
||||
@ -164,6 +180,14 @@ pub fn init_net() {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unimpl() -> IoError {
|
||||
IoError {
|
||||
kind: io::IoUnavailable,
|
||||
desc: "operation is not implemented",
|
||||
detail: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_utf16(s: Option<&str>) -> IoResult<Vec<u16>> {
|
||||
match s {
|
||||
Some(s) => Ok({
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
use prelude::*;
|
||||
|
||||
use fmt;
|
||||
use io::{IoResult, IoError};
|
||||
use iter::repeat;
|
||||
use libc::{c_int, c_void};
|
||||
|
@ -365,7 +365,7 @@ impl UnixStream {
|
||||
// acquire the lock.
|
||||
//
|
||||
// See comments in close_read() about why this lock is necessary.
|
||||
let guard = self.inner.lock.lock();
|
||||
let guard = unsafe { self.inner.lock.lock() };
|
||||
if self.read_closed() {
|
||||
return Err(eof())
|
||||
}
|
||||
@ -441,7 +441,7 @@ impl UnixStream {
|
||||
// going after we woke up.
|
||||
//
|
||||
// See comments in close_read() about why this lock is necessary.
|
||||
let guard = self.inner.lock.lock();
|
||||
let guard = unsafe { self.inner.lock.lock() };
|
||||
if self.write_closed() {
|
||||
return Err(epipe())
|
||||
}
|
||||
@ -516,14 +516,14 @@ impl UnixStream {
|
||||
// close_read() between steps 1 and 2. By atomically executing steps 1
|
||||
// and 2 with a lock with respect to close_read(), we're guaranteed that
|
||||
// no thread will erroneously sit in a read forever.
|
||||
let _guard = self.inner.lock.lock();
|
||||
let _guard = unsafe { self.inner.lock.lock() };
|
||||
self.inner.read_closed.store(true, atomic::SeqCst);
|
||||
self.cancel_io()
|
||||
}
|
||||
|
||||
pub fn close_write(&mut self) -> IoResult<()> {
|
||||
// see comments in close_read() for why this lock is necessary
|
||||
let _guard = self.inner.lock.lock();
|
||||
let _guard = unsafe { self.inner.lock.lock() };
|
||||
self.inner.write_closed.store(true, atomic::SeqCst);
|
||||
self.cancel_io()
|
||||
}
|
||||
|
@ -8,24 +8,25 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use prelude::*;
|
||||
|
||||
use libc::{pid_t, c_void};
|
||||
use libc::{pid_t, c_void, c_int};
|
||||
use libc;
|
||||
use c_str::CString;
|
||||
use io;
|
||||
use mem;
|
||||
use os;
|
||||
use ptr;
|
||||
use io::process::{ProcessExit, ExitStatus};
|
||||
use prelude::*;
|
||||
use io::process::{ProcessExit, ExitStatus, ExitSignal};
|
||||
use collections;
|
||||
use path::BytesContainer;
|
||||
use hash::Hash;
|
||||
use io::{IoResult, IoError};
|
||||
|
||||
use sys::timer;
|
||||
use sys::fs;
|
||||
use sys::{mod, retry, c, wouldblock, set_nonblocking, ms_to_timeval, timer};
|
||||
use sys::fs::FileDesc;
|
||||
use sys_common::{AsInner, timeout};
|
||||
use sys_common::helper_thread::Helper;
|
||||
use sys_common::{AsInner, mkerr_libc, timeout};
|
||||
|
||||
use io::fs::PathExtensions;
|
||||
|
||||
@ -120,6 +121,8 @@ impl Process {
|
||||
use libc::funcs::extra::msvcrt::get_osfhandle;
|
||||
|
||||
use mem;
|
||||
use iter::{Iterator, IteratorExt};
|
||||
use str::StrExt;
|
||||
|
||||
if cfg.gid().is_some() || cfg.uid().is_some() {
|
||||
return Err(IoError {
|
||||
|
@ -14,7 +14,7 @@ use ptr;
|
||||
use mem;
|
||||
use libc;
|
||||
use libc::types::os::arch::extra::{LPVOID, DWORD, LONG, BOOL};
|
||||
use sys_common::stack;
|
||||
use sys_common::{stack, thread_info};
|
||||
|
||||
pub struct Handler {
|
||||
_data: *mut libc::c_void
|
||||
@ -30,6 +30,14 @@ impl Drop for Handler {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
// get_task_info is called from an exception / signal handler.
|
||||
// It returns the guard page of the current task or 0 if that
|
||||
// guard page doesn't exist. None is returned if there's currently
|
||||
// no local task.
|
||||
unsafe fn get_task_guard_page() -> uint {
|
||||
thread_info::stack_guard()
|
||||
}
|
||||
|
||||
// This is initialized in init() and only read from after
|
||||
static mut PAGE_SIZE: uint = 0;
|
||||
|
||||
|
@ -14,10 +14,11 @@ use libc;
|
||||
use mem;
|
||||
use ptr;
|
||||
use prelude::*;
|
||||
use super::{last_error, last_net_error, sock_t};
|
||||
use super::{last_error, last_net_error, retry, sock_t};
|
||||
use sync::{Arc, atomic};
|
||||
use sys::fs::FileDesc;
|
||||
use sys::{mod, c, set_nonblocking, wouldblock, timer};
|
||||
use sys_common::{timeout, eof, net};
|
||||
use sys_common::{mod, timeout, eof, net};
|
||||
|
||||
pub use sys_common::net::TcpStream;
|
||||
|
||||
@ -204,6 +205,10 @@ impl TcpAcceptor {
|
||||
Err(eof())
|
||||
}
|
||||
|
||||
pub fn socket_name(&mut self) -> IoResult<ip::SocketAddr> {
|
||||
net::sockname(self.socket(), libc::getsockname)
|
||||
}
|
||||
|
||||
pub fn set_timeout(&mut self, timeout: Option<u64>) {
|
||||
self.deadline = timeout.map(|a| timer::now() + a).unwrap_or(0);
|
||||
}
|
||||
|
@ -8,6 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use core::prelude::*;
|
||||
|
||||
use boxed::Box;
|
||||
use cmp;
|
||||
use mem;
|
||||
|
@ -137,9 +137,9 @@ unsafe fn init_dtors() {
|
||||
rt::at_exit(move|| {
|
||||
DTOR_LOCK.lock();
|
||||
let dtors = DTORS;
|
||||
DTORS = 1 as *mut _;
|
||||
DTORS = 0 as *mut _;
|
||||
mem::transmute::<_, Box<Vec<(Key, Dtor)>>>(dtors);
|
||||
assert!(DTORS as uint == 1); // can't re-init after destructing
|
||||
assert!(DTORS.is_null()); // can't re-init after destructing
|
||||
DTOR_LOCK.unlock();
|
||||
});
|
||||
}
|
||||
@ -147,9 +147,6 @@ unsafe fn init_dtors() {
|
||||
unsafe fn register_dtor(key: Key, dtor: Dtor) {
|
||||
DTOR_LOCK.lock();
|
||||
init_dtors();
|
||||
assert!(DTORS as uint != 0);
|
||||
assert!(DTORS as uint != 1,
|
||||
"cannot create new TLS keys after the main thread has exited");
|
||||
(*DTORS).push((key, dtor));
|
||||
DTOR_LOCK.unlock();
|
||||
}
|
||||
@ -157,9 +154,6 @@ unsafe fn register_dtor(key: Key, dtor: Dtor) {
|
||||
unsafe fn unregister_dtor(key: Key) -> bool {
|
||||
DTOR_LOCK.lock();
|
||||
init_dtors();
|
||||
assert!(DTORS as uint != 0);
|
||||
assert!(DTORS as uint != 1,
|
||||
"cannot unregister destructors after the main thread has exited");
|
||||
let ret = {
|
||||
let dtors = &mut *DTORS;
|
||||
let before = dtors.len();
|
||||
@ -238,7 +232,6 @@ unsafe extern "system" fn on_tls_callback(h: LPVOID,
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)] // not actually dead
|
||||
unsafe fn run_dtors() {
|
||||
let mut any_run = true;
|
||||
for _ in range(0, 5i) {
|
||||
|
@ -26,6 +26,8 @@ use libc;
|
||||
use ptr;
|
||||
use comm;
|
||||
|
||||
use sys::c;
|
||||
use sys::fs::FileDesc;
|
||||
use sys_common::helper_thread::Helper;
|
||||
use prelude::*;
|
||||
use io::IoResult;
|
||||
@ -78,10 +80,9 @@ fn helper(input: libc::HANDLE, messages: Receiver<Req>, _: ()) {
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
// See the comment in unix::timer for why we don't have any
|
||||
// asserts here and why we're likely just leaving timers on
|
||||
// the floor as we exit.
|
||||
Err(comm::Disconnected) => {
|
||||
assert_eq!(objs.len(), 1);
|
||||
assert_eq!(chans.len(), 0);
|
||||
break 'outer;
|
||||
}
|
||||
Err(..) => break
|
||||
|
@ -26,6 +26,7 @@
|
||||
//! to working in raw UTF-16, with such a wrapper around it.
|
||||
|
||||
use super::c::{ReadConsoleW, WriteConsoleW, GetConsoleMode, SetConsoleMode};
|
||||
use super::c::{ERROR_ILLEGAL_CHARACTER};
|
||||
use super::c::{ENABLE_ECHO_INPUT, ENABLE_EXTENDED_FLAGS};
|
||||
use super::c::{ENABLE_INSERT_MODE, ENABLE_LINE_INPUT};
|
||||
use super::c::{ENABLE_PROCESSED_INPUT, ENABLE_QUICK_EDIT_MODE};
|
||||
@ -38,8 +39,6 @@ use prelude::*;
|
||||
use ptr;
|
||||
use str::from_utf8;
|
||||
|
||||
use sys_common::unimpl;
|
||||
|
||||
fn invalid_encoding() -> IoError {
|
||||
IoError {
|
||||
kind: io::InvalidInput,
|
||||
@ -151,8 +150,11 @@ impl TTY {
|
||||
// Make a CONSOLE_SCREEN_BUFFER_INFO
|
||||
// Call GetConsoleScreenBufferInfo
|
||||
// Maybe call GetLargestConsoleWindowSize instead?
|
||||
Err(unimpl())
|
||||
Err(super::unimpl())
|
||||
}
|
||||
|
||||
// Let us magically declare this as a TTY
|
||||
pub fn isatty(&self) -> bool { true }
|
||||
}
|
||||
|
||||
impl Drop for TTY {
|
||||
|
@ -232,10 +232,13 @@ impl Builder {
|
||||
let my_stack_top = addr as uint;
|
||||
let my_stack_bottom = my_stack_top - stack_size + 1024;
|
||||
unsafe {
|
||||
stack::record_os_managed_stack_bounds(my_stack_bottom,
|
||||
my_stack_top);
|
||||
thread_info::set(imp::guard::current(), their_thread);
|
||||
stack::record_os_managed_stack_bounds(my_stack_bottom, my_stack_top);
|
||||
}
|
||||
thread_info::set(
|
||||
(my_stack_bottom, my_stack_top),
|
||||
unsafe { imp::guard::current() },
|
||||
their_thread
|
||||
);
|
||||
|
||||
let mut output = None;
|
||||
let f: Thunk<(), T> = if stdout.is_some() || stderr.is_some() {
|
||||
|
Loading…
Reference in New Issue
Block a user