std: Internalize almost all of std::rt
This commit does some refactoring to make almost all of the `std::rt` private. Specifically, the following items are no longer part of its API: * DEFAULT_ERROR_CODE * backtrace * unwind * args * at_exit * cleanup * heap (this is just alloc::heap) * min_stack * util The module is now tagged as `#[doc(hidden)]` as the only purpose it's serve is an entry point for the `panic!` macro via the `begin_unwind` and `begin_unwind_fmt` reexports.
This commit is contained in:
parent
192c37537b
commit
f4be2026df
33 changed files with 273 additions and 432 deletions
|
@ -26,13 +26,16 @@ this is totally fine.
|
|||
For instance, a custom implementation of `Box` might write `Drop` like this:
|
||||
|
||||
```rust
|
||||
#![feature(heap_api, core_intrinsics, unique)]
|
||||
#![feature(alloc, heap_api, core_intrinsics, unique)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use std::rt::heap;
|
||||
use std::ptr::Unique;
|
||||
use std::intrinsics::drop_in_place;
|
||||
use std::mem;
|
||||
|
||||
use alloc::heap;
|
||||
|
||||
struct Box<T>{ ptr: Unique<T> }
|
||||
|
||||
impl<T> Drop for Box<T> {
|
||||
|
@ -45,6 +48,7 @@ impl<T> Drop for Box<T> {
|
|||
}
|
||||
}
|
||||
}
|
||||
# fn main() {}
|
||||
```
|
||||
|
||||
and this works fine because when Rust goes to drop the `ptr` field it just sees
|
||||
|
@ -54,13 +58,16 @@ use-after-free the `ptr` because when drop exits, it becomes inacessible.
|
|||
However this wouldn't work:
|
||||
|
||||
```rust
|
||||
#![feature(heap_api, core_intrinsics, unique)]
|
||||
#![feature(alloc, heap_api, core_intrinsics, unique)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use std::rt::heap;
|
||||
use std::ptr::Unique;
|
||||
use std::intrinsics::drop_in_place;
|
||||
use std::mem;
|
||||
|
||||
use alloc::heap;
|
||||
|
||||
struct Box<T>{ ptr: Unique<T> }
|
||||
|
||||
impl<T> Drop for Box<T> {
|
||||
|
@ -87,6 +94,7 @@ impl<T> Drop for SuperBox<T> {
|
|||
}
|
||||
}
|
||||
}
|
||||
# fn main() {}
|
||||
```
|
||||
|
||||
After we deallocate the `box`'s ptr in SuperBox's destructor, Rust will
|
||||
|
@ -129,13 +137,16 @@ The classic safe solution to overriding recursive drop and allowing moving out
|
|||
of Self during `drop` is to use an Option:
|
||||
|
||||
```rust
|
||||
#![feature(heap_api, core_intrinsics, unique)]
|
||||
#![feature(alloc, heap_api, core_intrinsics, unique)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use std::rt::heap;
|
||||
use std::ptr::Unique;
|
||||
use std::intrinsics::drop_in_place;
|
||||
use std::mem;
|
||||
|
||||
use alloc::heap;
|
||||
|
||||
struct Box<T>{ ptr: Unique<T> }
|
||||
|
||||
impl<T> Drop for Box<T> {
|
||||
|
@ -165,6 +176,7 @@ impl<T> Drop for SuperBox<T> {
|
|||
}
|
||||
}
|
||||
}
|
||||
# fn main() {}
|
||||
```
|
||||
|
||||
However this has fairly odd semantics: you're saying that a field that *should*
|
||||
|
|
|
@ -9,7 +9,7 @@ This is perfectly fine because we already have `cap == 0` as our sentinel for no
|
|||
allocation. We don't even need to handle it specially in almost any code because
|
||||
we usually need to check if `cap > len` or `len > 0` anyway. The traditional
|
||||
Rust value to put here is `0x01`. The standard library actually exposes this
|
||||
as `std::rt::heap::EMPTY`. There are quite a few places where we'll
|
||||
as `alloc::heap::EMPTY`. There are quite a few places where we'll
|
||||
want to use `heap::EMPTY` because there's no real allocation to talk about but
|
||||
`null` would make the compiler do bad things.
|
||||
|
||||
|
@ -20,11 +20,12 @@ the `heap` API anyway, so let's just get that dependency over with.
|
|||
So:
|
||||
|
||||
```rust,ignore
|
||||
#![feature(heap_api)]
|
||||
#![feature(alloc, heap_api)]
|
||||
|
||||
use std::rt::heap::EMPTY;
|
||||
use std::mem;
|
||||
|
||||
use alloc::heap::EMPTY;
|
||||
|
||||
impl<T> Vec<T> {
|
||||
fn new() -> Self {
|
||||
assert!(mem::size_of::<T>() != 0, "We're not ready to handle ZSTs");
|
||||
|
|
|
@ -2,17 +2,16 @@
|
|||
|
||||
```rust
|
||||
#![feature(unique)]
|
||||
#![feature(heap_api)]
|
||||
#![feature(alloc, heap_api)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use std::ptr::{Unique, self};
|
||||
use std::rt::heap;
|
||||
use std::mem;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
|
||||
|
||||
|
||||
use alloc::heap;
|
||||
|
||||
struct RawVec<T> {
|
||||
ptr: Unique<T>,
|
||||
|
|
|
@ -49,7 +49,8 @@ use std::marker;
|
|||
use std::mem;
|
||||
use std::ptr;
|
||||
use std::rc::Rc;
|
||||
use std::rt::heap::{allocate, deallocate};
|
||||
|
||||
use alloc::heap::{allocate, deallocate};
|
||||
|
||||
// The way arena uses arrays is really deeply awful. The arrays are
|
||||
// allocated, and have capacities reserved, but the fill for the array
|
||||
|
|
|
@ -174,7 +174,6 @@
|
|||
#![feature(box_syntax)]
|
||||
#![feature(const_fn)]
|
||||
#![feature(iter_cmp)]
|
||||
#![feature(rt)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(static_mutex)]
|
||||
|
||||
|
@ -185,7 +184,6 @@ use std::io::prelude::*;
|
|||
use std::mem;
|
||||
use std::env;
|
||||
use std::ptr;
|
||||
use std::rt;
|
||||
use std::slice;
|
||||
use std::sync::{Once, StaticMutex};
|
||||
|
||||
|
@ -292,7 +290,6 @@ pub fn log(level: u32, loc: &'static LogLocation, args: fmt::Arguments) {
|
|||
let _g = LOCK.lock();
|
||||
match FILTER as usize {
|
||||
0 => {}
|
||||
1 => panic!("cannot log after main thread has exited"),
|
||||
n => {
|
||||
let filter = mem::transmute::<_, &String>(n);
|
||||
if !args.to_string().contains(filter) {
|
||||
|
@ -385,9 +382,6 @@ pub fn mod_enabled(level: u32, module: &str) -> bool {
|
|||
let _g = LOCK.lock();
|
||||
unsafe {
|
||||
assert!(DIRECTIVES as usize != 0);
|
||||
assert!(DIRECTIVES as usize != 1,
|
||||
"cannot log after the main thread has exited");
|
||||
|
||||
enabled(level, module, (*DIRECTIVES).iter())
|
||||
}
|
||||
}
|
||||
|
@ -442,19 +436,6 @@ fn init() {
|
|||
|
||||
assert!(DIRECTIVES.is_null());
|
||||
DIRECTIVES = Box::into_raw(box directives);
|
||||
|
||||
// Schedule the cleanup for the globals for when the runtime exits.
|
||||
let _ = rt::at_exit(move || {
|
||||
let _g = LOCK.lock();
|
||||
assert!(!DIRECTIVES.is_null());
|
||||
let _directives = Box::from_raw(DIRECTIVES);
|
||||
DIRECTIVES = 1 as *mut _;
|
||||
|
||||
if !FILTER.is_null() {
|
||||
let _filter = Box::from_raw(FILTER);
|
||||
FILTER = 1 as *mut _;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,23 +8,20 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use self::BucketState::*;
|
||||
use alloc::heap::{allocate, deallocate, EMPTY};
|
||||
|
||||
use clone::Clone;
|
||||
use cmp;
|
||||
use hash::{Hash, Hasher};
|
||||
use iter::{Iterator, ExactSizeIterator};
|
||||
use marker::{Copy, Send, Sync, Sized, self};
|
||||
use marker;
|
||||
use mem::{align_of, size_of};
|
||||
use mem;
|
||||
use num::wrapping::OverflowingOps;
|
||||
use ops::{Deref, DerefMut, Drop};
|
||||
use option::Option;
|
||||
use option::Option::{Some, None};
|
||||
use ops::{Deref, DerefMut};
|
||||
use ptr::{self, Unique};
|
||||
use rt::heap::{allocate, deallocate, EMPTY};
|
||||
use collections::hash_state::HashState;
|
||||
|
||||
use self::BucketState::*;
|
||||
|
||||
const EMPTY_BUCKET: u64 = 0;
|
||||
|
||||
/// The raw hashtable, providing safe-ish access to the unzipped and highly
|
||||
|
|
|
@ -12,8 +12,8 @@ use prelude::v1::*;
|
|||
|
||||
use cell::Cell;
|
||||
use ptr;
|
||||
use rt;
|
||||
use sync::{StaticMutex, Arc};
|
||||
use sys_common;
|
||||
|
||||
pub struct Lazy<T> {
|
||||
lock: StaticMutex,
|
||||
|
@ -51,7 +51,7 @@ impl<T: Send + Sync + 'static> Lazy<T> {
|
|||
// `Arc` allocation in our own internal box (it will get deallocated by
|
||||
// the at exit handler). Otherwise we just return the freshly allocated
|
||||
// `Arc`.
|
||||
let registered = rt::at_exit(move || {
|
||||
let registered = sys_common::at_exit(move || {
|
||||
let g = self.lock.lock();
|
||||
let ptr = self.ptr.get();
|
||||
self.ptr.set(1 as *mut _);
|
||||
|
|
|
@ -13,9 +13,10 @@ use io::prelude::*;
|
|||
|
||||
use any::Any;
|
||||
use cell::RefCell;
|
||||
use rt::{backtrace, unwind};
|
||||
use sys::stdio::Stderr;
|
||||
use sys_common::backtrace;
|
||||
use sys_common::thread_info;
|
||||
use sys_common::unwind;
|
||||
|
||||
thread_local! {
|
||||
pub static LOCAL_STDERR: RefCell<Option<Box<Write + Send>>> = {
|
||||
|
|
|
@ -582,7 +582,7 @@ impl Child {
|
|||
/// to run.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn exit(code: i32) -> ! {
|
||||
::rt::cleanup();
|
||||
::sys_common::cleanup();
|
||||
::sys::os::exit(code)
|
||||
}
|
||||
|
||||
|
|
65
src/libstd/rt.rs
Normal file
65
src/libstd/rt.rs
Normal file
|
@ -0,0 +1,65 @@
|
|||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <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.
|
||||
|
||||
//! Runtime services
|
||||
//!
|
||||
//! The `rt` module provides a narrow set of runtime services,
|
||||
//! including the global heap (exported in `heap`) and unwinding and
|
||||
//! backtrace support. The APIs in this module are highly unstable,
|
||||
//! and should be considered as private implementation details for the
|
||||
//! time being.
|
||||
|
||||
#![unstable(feature = "rt",
|
||||
reason = "this public module should not exist and is highly likely \
|
||||
to disappear",
|
||||
issue = "0")]
|
||||
#![doc(hidden)]
|
||||
|
||||
use borrow::ToOwned;
|
||||
use mem;
|
||||
use sys;
|
||||
use sys_common::thread_info::{self, NewThread};
|
||||
use sys_common;
|
||||
use thread::{self, Thread};
|
||||
|
||||
// Reexport some of our utilities which are expected by other crates.
|
||||
pub use sys_common::unwind::{begin_unwind, begin_unwind_fmt};
|
||||
|
||||
#[cfg(not(test))]
|
||||
#[lang = "start"]
|
||||
fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize {
|
||||
sys::init();
|
||||
|
||||
let failed = unsafe {
|
||||
let main_guard = sys::thread::guard::init();
|
||||
sys::stack_overflow::init();
|
||||
|
||||
// Next, set up the current Thread with the guard information we just
|
||||
// created. Note that this isn't necessary in general for new threads,
|
||||
// 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_owned()));
|
||||
thread_info::set(main_guard, thread);
|
||||
|
||||
// Store our args if necessary in a squirreled away location
|
||||
sys_common::args::init(argc, argv);
|
||||
|
||||
// Let's run some code!
|
||||
let res = thread::catch_panic(mem::transmute::<_, fn()>(main));
|
||||
sys_common::cleanup();
|
||||
res.is_err()
|
||||
};
|
||||
|
||||
if failed {
|
||||
101
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <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.
|
||||
|
||||
//! Simple backtrace functionality (to print on panic)
|
||||
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
use env;
|
||||
use sync::atomic::{self, Ordering};
|
||||
|
||||
pub use sys::backtrace::write;
|
||||
|
||||
// For now logging is turned off by default, and this function checks to see
|
||||
// whether the magical environment variable is present to see if it's turned on.
|
||||
pub fn log_enabled() -> bool {
|
||||
static ENABLED: atomic::AtomicIsize = atomic::AtomicIsize::new(0);
|
||||
match ENABLED.load(Ordering::SeqCst) {
|
||||
1 => return false,
|
||||
2 => return true,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let val = match env::var_os("RUST_BACKTRACE") {
|
||||
Some(..) => 2,
|
||||
None => 1,
|
||||
};
|
||||
ENABLED.store(val, Ordering::SeqCst);
|
||||
val == 2
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use prelude::v1::*;
|
||||
use sys_common;
|
||||
macro_rules! t { ($a:expr, $b:expr) => ({
|
||||
let mut m = Vec::new();
|
||||
sys_common::backtrace::demangle(&mut m, $a).unwrap();
|
||||
assert_eq!(String::from_utf8(m).unwrap(), $b);
|
||||
}) }
|
||||
|
||||
#[test]
|
||||
fn demangle() {
|
||||
t!("test", "test");
|
||||
t!("_ZN4testE", "test");
|
||||
t!("_ZN4test", "_ZN4test");
|
||||
t!("_ZN4test1a2bcE", "test::a::bc");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn demangle_dollars() {
|
||||
t!("_ZN4$RP$E", ")");
|
||||
t!("_ZN8$RF$testE", "&test");
|
||||
t!("_ZN8$BP$test4foobE", "*test::foob");
|
||||
t!("_ZN9$u20$test4foobE", " test::foob");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn demangle_many_dollars() {
|
||||
t!("_ZN13test$u20$test4foobE", "test test::foob");
|
||||
t!("_ZN12test$BP$test4foobE", "test*test::foob");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn demangle_windows() {
|
||||
t!("ZN4testE", "test");
|
||||
t!("ZN13test$u20$test4foobE", "test test::foob");
|
||||
t!("ZN12test$RF$test4foobE", "test&test::foob");
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <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.
|
||||
|
||||
//! Macros used by the runtime.
|
||||
//!
|
||||
//! These macros call functions which are only accessible in the `rt` module, so
|
||||
//! they aren't defined anywhere outside of the `rt` module.
|
||||
|
||||
macro_rules! rterrln {
|
||||
($fmt:expr) => ( {
|
||||
::rt::util::dumb_print(format_args!(concat!($fmt, "\n")))
|
||||
} );
|
||||
($fmt:expr, $($arg:expr),*) => ( {
|
||||
::rt::util::dumb_print(format_args!(concat!($fmt, "\n"), $($arg),*))
|
||||
} )
|
||||
}
|
||||
|
||||
// Some basic logging. Enabled by passing `--cfg rtdebug` to the libstd build.
|
||||
macro_rules! rtdebug {
|
||||
($arg:expr) => ( {
|
||||
if cfg!(rtdebug) {
|
||||
rterrln!($arg)
|
||||
}
|
||||
} );
|
||||
($str:expr, $($arg:expr),*) => ( {
|
||||
if cfg!(rtdebug) {
|
||||
rterrln!($str, $($arg),*)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
macro_rules! rtassert {
|
||||
( $arg:expr ) => ( {
|
||||
if ::rt::util::ENFORCE_SANITY {
|
||||
if !$arg {
|
||||
rtabort!(" assertion failed: {}", stringify!($arg));
|
||||
}
|
||||
}
|
||||
} )
|
||||
}
|
||||
|
||||
macro_rules! rtabort {
|
||||
($($arg:tt)*) => (::rt::util::abort(format_args!($($arg)*)))
|
||||
}
|
|
@ -1,135 +0,0 @@
|
|||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <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.
|
||||
|
||||
//! Runtime services
|
||||
//!
|
||||
//! The `rt` module provides a narrow set of runtime services,
|
||||
//! including the global heap (exported in `heap`) and unwinding and
|
||||
//! backtrace support. The APIs in this module are highly unstable,
|
||||
//! and should be considered as private implementation details for the
|
||||
//! time being.
|
||||
|
||||
#![unstable(feature = "rt",
|
||||
reason = "this public module should not exist and is highly likely \
|
||||
to disappear",
|
||||
issue = "0")]
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use prelude::v1::*;
|
||||
use sync::Once;
|
||||
use sys;
|
||||
use thread;
|
||||
|
||||
// Reexport some of our utilities which are expected by other crates.
|
||||
pub use self::util::min_stack;
|
||||
pub use self::unwind::{begin_unwind, begin_unwind_fmt};
|
||||
|
||||
// Reexport some functionality from liballoc.
|
||||
pub use alloc::heap;
|
||||
|
||||
// Simple backtrace functionality (to print on panic)
|
||||
pub mod backtrace;
|
||||
|
||||
// Internals
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
// These should be refactored/moved/made private over time
|
||||
pub mod util;
|
||||
pub mod unwind;
|
||||
pub mod args;
|
||||
|
||||
mod at_exit_imp;
|
||||
mod libunwind;
|
||||
|
||||
mod dwarf;
|
||||
|
||||
/// The default error code of the rust runtime if the main thread panics instead
|
||||
/// of exiting cleanly.
|
||||
pub const DEFAULT_ERROR_CODE: isize = 101;
|
||||
|
||||
#[cfg(not(test))]
|
||||
#[lang = "start"]
|
||||
fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize {
|
||||
use prelude::v1::*;
|
||||
|
||||
use mem;
|
||||
use rt;
|
||||
use sys_common::thread_info::{self, NewThread};
|
||||
use thread::Thread;
|
||||
|
||||
let failed = unsafe {
|
||||
let main_guard = sys::thread::guard::init();
|
||||
sys::stack_overflow::init();
|
||||
|
||||
// Next, set up the current Thread with the guard information we just
|
||||
// created. Note that this isn't necessary in general for new threads,
|
||||
// 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_owned()));
|
||||
thread_info::set(main_guard, thread);
|
||||
|
||||
// By default, some platforms will send a *signal* when a EPIPE error
|
||||
// would otherwise be delivered. This runtime doesn't install a SIGPIPE
|
||||
// handler, causing it to kill the program, which isn't exactly what we
|
||||
// want!
|
||||
//
|
||||
// Hence, we set SIGPIPE to ignore when the program starts up in order
|
||||
// to prevent this problem.
|
||||
#[cfg(windows)] fn ignore_sigpipe() {}
|
||||
#[cfg(unix)] fn ignore_sigpipe() {
|
||||
use libc;
|
||||
use libc::funcs::posix01::signal::signal;
|
||||
unsafe {
|
||||
assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != !0);
|
||||
}
|
||||
}
|
||||
ignore_sigpipe();
|
||||
|
||||
// Store our args if necessary in a squirreled away location
|
||||
args::init(argc, argv);
|
||||
|
||||
// And finally, let's run some code!
|
||||
let res = thread::catch_panic(mem::transmute::<_, fn()>(main));
|
||||
cleanup();
|
||||
res.is_err()
|
||||
};
|
||||
|
||||
// If the exit code wasn't set, then the try block must have panicked.
|
||||
if failed {
|
||||
rt::DEFAULT_ERROR_CODE
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
/// Enqueues a procedure to run when the main thread exits.
|
||||
///
|
||||
/// Currently these closures are only run once the main *Rust* thread exits.
|
||||
/// Once the `at_exit` handlers begin running, more may be enqueued, but not
|
||||
/// infinitely so. Eventually a handler registration will be forced to fail.
|
||||
///
|
||||
/// Returns `Ok` if the handler was successfully registered, meaning that the
|
||||
/// closure will be run once the main thread exits. Returns `Err` to indicate
|
||||
/// that the closure could not be registered, meaning that it is not scheduled
|
||||
/// to be run.
|
||||
pub fn at_exit<F: FnOnce() + Send + 'static>(f: F) -> Result<(), ()> {
|
||||
if at_exit_imp::push(Box::new(f)) {Ok(())} else {Err(())}
|
||||
}
|
||||
|
||||
/// One-time runtime cleanup.
|
||||
pub fn cleanup() {
|
||||
static CLEANUP: Once = Once::new();
|
||||
CLEANUP.call_once(|| unsafe {
|
||||
args::cleanup();
|
||||
sys::stack_overflow::cleanup();
|
||||
at_exit_imp::cleanup();
|
||||
});
|
||||
}
|
|
@ -19,6 +19,8 @@
|
|||
//!
|
||||
//! FIXME #7756: Would be nice for this to not exist.
|
||||
|
||||
#![allow(dead_code)] // different code on OSX/linux/etc
|
||||
|
||||
use vec::Vec;
|
||||
|
||||
/// One-time global initialization.
|
||||
|
@ -27,14 +29,6 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) { imp::init(argc, argv)
|
|||
/// One-time global cleanup.
|
||||
pub unsafe fn cleanup() { imp::cleanup() }
|
||||
|
||||
/// Take the global arguments from global storage.
|
||||
pub fn take() -> Option<Vec<Vec<u8>>> { imp::take() }
|
||||
|
||||
/// Give the global arguments to global storage.
|
||||
///
|
||||
/// It is an error if the arguments already exist.
|
||||
pub fn put(args: Vec<Vec<u8>>) { imp::put(args) }
|
||||
|
||||
/// Make a clone of the global arguments.
|
||||
pub fn clone() -> Option<Vec<Vec<u8>>> { imp::clone() }
|
||||
|
||||
|
@ -48,7 +42,7 @@ pub fn clone() -> Option<Vec<Vec<u8>>> { imp::clone() }
|
|||
mod imp {
|
||||
use prelude::v1::*;
|
||||
|
||||
use libc;
|
||||
use libc::c_char;
|
||||
use mem;
|
||||
use ffi::CStr;
|
||||
|
||||
|
@ -58,37 +52,26 @@ mod imp {
|
|||
static LOCK: StaticMutex = StaticMutex::new();
|
||||
|
||||
pub unsafe fn init(argc: isize, argv: *const *const u8) {
|
||||
let args = load_argc_and_argv(argc, argv);
|
||||
put(args);
|
||||
let args = (0..argc).map(|i| {
|
||||
CStr::from_ptr(*argv.offset(i) as *const c_char).to_bytes().to_vec()
|
||||
}).collect();
|
||||
|
||||
let _guard = LOCK.lock();
|
||||
let ptr = get_global_ptr();
|
||||
assert!((*ptr).is_none());
|
||||
(*ptr) = Some(box args);
|
||||
}
|
||||
|
||||
pub unsafe fn cleanup() {
|
||||
take();
|
||||
}
|
||||
|
||||
pub fn take() -> Option<Vec<Vec<u8>>> {
|
||||
let _guard = LOCK.lock();
|
||||
unsafe {
|
||||
let ptr = get_global_ptr();
|
||||
let val = mem::replace(&mut *ptr, None);
|
||||
val.as_ref().map(|s: &Box<Vec<Vec<u8>>>| (**s).clone())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn put(args: Vec<Vec<u8>>) {
|
||||
let _guard = LOCK.lock();
|
||||
unsafe {
|
||||
let ptr = get_global_ptr();
|
||||
rtassert!((*ptr).is_none());
|
||||
(*ptr) = Some(box args.clone());
|
||||
}
|
||||
*get_global_ptr() = None;
|
||||
}
|
||||
|
||||
pub fn clone() -> Option<Vec<Vec<u8>>> {
|
||||
let _guard = LOCK.lock();
|
||||
unsafe {
|
||||
let ptr = get_global_ptr();
|
||||
(*ptr).as_ref().map(|s: &Box<Vec<Vec<u8>>>| (**s).clone())
|
||||
(*ptr).as_ref().map(|s| (**s).clone())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,42 +79,6 @@ mod imp {
|
|||
unsafe { mem::transmute(&GLOBAL_ARGS_PTR) }
|
||||
}
|
||||
|
||||
unsafe fn load_argc_and_argv(argc: isize,
|
||||
argv: *const *const u8) -> Vec<Vec<u8>> {
|
||||
let argv = argv as *const *const libc::c_char;
|
||||
(0..argc).map(|i| {
|
||||
CStr::from_ptr(*argv.offset(i)).to_bytes().to_vec()
|
||||
}).collect()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use prelude::v1::*;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn smoke_test() {
|
||||
// Preserve the actual global state.
|
||||
let saved_value = take();
|
||||
|
||||
let expected = vec![
|
||||
b"happy".to_vec(),
|
||||
b"today?".to_vec(),
|
||||
];
|
||||
|
||||
put(expected.clone());
|
||||
assert!(clone() == Some(expected.clone()));
|
||||
assert!(take() == Some(expected.clone()));
|
||||
assert!(take() == None);
|
||||
|
||||
// Restore the actual global state.
|
||||
match saved_value {
|
||||
Some(ref args) => put(args.clone()),
|
||||
None => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "macos",
|
||||
|
@ -146,14 +93,6 @@ mod imp {
|
|||
pub fn cleanup() {
|
||||
}
|
||||
|
||||
pub fn take() -> Option<Vec<Vec<u8>>> {
|
||||
panic!()
|
||||
}
|
||||
|
||||
pub fn put(_args: Vec<Vec<u8>>) {
|
||||
panic!()
|
||||
}
|
||||
|
||||
pub fn clone() -> Option<Vec<Vec<u8>>> {
|
||||
panic!()
|
||||
}
|
|
@ -54,7 +54,7 @@ pub fn cleanup() {
|
|||
LOCK.unlock();
|
||||
|
||||
// make sure we're not recursively cleaning up
|
||||
rtassert!(queue as usize != 1);
|
||||
assert!(queue as usize != 1);
|
||||
|
||||
// If we never called init, not need to cleanup!
|
||||
if queue as usize != 0 {
|
|
@ -8,10 +8,14 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use io;
|
||||
use env;
|
||||
use io::prelude::*;
|
||||
use str;
|
||||
use io;
|
||||
use libc;
|
||||
use str;
|
||||
use sync::atomic::{self, Ordering};
|
||||
|
||||
pub use sys::backtrace::write;
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub const HEX_WIDTH: usize = 18;
|
||||
|
@ -19,6 +23,23 @@ pub const HEX_WIDTH: usize = 18;
|
|||
#[cfg(target_pointer_width = "32")]
|
||||
pub const HEX_WIDTH: usize = 10;
|
||||
|
||||
// For now logging is turned off by default, and this function checks to see
|
||||
// whether the magical environment variable is present to see if it's turned on.
|
||||
pub fn log_enabled() -> bool {
|
||||
static ENABLED: atomic::AtomicIsize = atomic::AtomicIsize::new(0);
|
||||
match ENABLED.load(Ordering::SeqCst) {
|
||||
1 => return false,
|
||||
2 => return true,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let val = match env::var_os("RUST_BACKTRACE") {
|
||||
Some(..) => 2,
|
||||
None => 1,
|
||||
};
|
||||
ENABLED.store(val, Ordering::SeqCst);
|
||||
val == 2
|
||||
}
|
||||
|
||||
// These output functions should now be used everywhere to ensure consistency.
|
||||
pub fn output(w: &mut Write, idx: isize, addr: *mut libc::c_void,
|
||||
|
@ -163,3 +184,43 @@ pub fn demangle(writer: &mut Write, s: &str) -> io::Result<()> {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use prelude::v1::*;
|
||||
use sys_common;
|
||||
macro_rules! t { ($a:expr, $b:expr) => ({
|
||||
let mut m = Vec::new();
|
||||
sys_common::backtrace::demangle(&mut m, $a).unwrap();
|
||||
assert_eq!(String::from_utf8(m).unwrap(), $b);
|
||||
}) }
|
||||
|
||||
#[test]
|
||||
fn demangle() {
|
||||
t!("test", "test");
|
||||
t!("_ZN4testE", "test");
|
||||
t!("_ZN4test", "_ZN4test");
|
||||
t!("_ZN4test1a2bcE", "test::a::bc");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn demangle_dollars() {
|
||||
t!("_ZN4$RP$E", ")");
|
||||
t!("_ZN8$RF$testE", "&test");
|
||||
t!("_ZN8$BP$test4foobE", "*test::foob");
|
||||
t!("_ZN9$u20$test4foobE", " test::foob");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn demangle_many_dollars() {
|
||||
t!("_ZN13test$u20$test4foobE", "test test::foob");
|
||||
t!("_ZN12test$BP$test4foobE", "test*test::foob");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn demangle_windows() {
|
||||
t!("ZN4testE", "test");
|
||||
t!("ZN13test$u20$test4foobE", "test test::foob");
|
||||
t!("ZN12test$RF$test4foobE", "test&test::foob");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#![allow(unused)]
|
||||
|
||||
use prelude::v1::*;
|
||||
use rt::dwarf::DwarfReader;
|
||||
use sys_common::dwarf::DwarfReader;
|
||||
use core::mem;
|
||||
|
||||
pub const DW_EH_PE_omit : u8 = 0xFF;
|
|
@ -10,17 +10,39 @@
|
|||
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use boxed::Box;
|
||||
use sync::Once;
|
||||
use sys;
|
||||
|
||||
macro_rules! rtabort {
|
||||
($($t:tt)*) => (::sys_common::util::abort(format_args!($($t)*)))
|
||||
}
|
||||
|
||||
macro_rules! rtassert {
|
||||
($e:expr) => ({
|
||||
if !$e {
|
||||
rtabort!(concat!("assertion failed: ", stringify!($e)))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub mod args;
|
||||
pub mod at_exit_imp;
|
||||
pub mod backtrace;
|
||||
pub mod condvar;
|
||||
pub mod dwarf;
|
||||
pub mod io;
|
||||
pub mod libunwind;
|
||||
pub mod mutex;
|
||||
pub mod net;
|
||||
pub mod io;
|
||||
pub mod poison;
|
||||
pub mod remutex;
|
||||
pub mod rwlock;
|
||||
pub mod thread;
|
||||
pub mod thread_info;
|
||||
pub mod thread_local;
|
||||
pub mod unwind;
|
||||
pub mod util;
|
||||
pub mod wtf8;
|
||||
|
||||
#[cfg(any(all(unix, not(any(target_os = "macos", target_os = "ios"))),
|
||||
|
@ -52,3 +74,27 @@ pub trait IntoInner<Inner> {
|
|||
pub trait FromInner<Inner> {
|
||||
fn from_inner(inner: Inner) -> Self;
|
||||
}
|
||||
|
||||
/// Enqueues a procedure to run when the main thread exits.
|
||||
///
|
||||
/// Currently these closures are only run once the main *Rust* thread exits.
|
||||
/// Once the `at_exit` handlers begin running, more may be enqueued, but not
|
||||
/// infinitely so. Eventually a handler registration will be forced to fail.
|
||||
///
|
||||
/// Returns `Ok` if the handler was successfully registered, meaning that the
|
||||
/// closure will be run once the main thread exits. Returns `Err` to indicate
|
||||
/// that the closure could not be registered, meaning that it is not scheduled
|
||||
/// to be run.
|
||||
pub fn at_exit<F: FnOnce() + Send + 'static>(f: F) -> Result<(), ()> {
|
||||
if at_exit_imp::push(Box::new(f)) {Ok(())} else {Err(())}
|
||||
}
|
||||
|
||||
/// One-time runtime cleanup.
|
||||
pub fn cleanup() {
|
||||
static CLEANUP: Once = Once::new();
|
||||
CLEANUP.call_once(|| unsafe {
|
||||
args::cleanup();
|
||||
sys::stack_overflow::cleanup();
|
||||
at_exit_imp::cleanup();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
use prelude::v1::*;
|
||||
|
||||
use any::Any;
|
||||
use rt::libunwind as uw;
|
||||
use sys_common::libunwind as uw;
|
||||
|
||||
struct Exception {
|
||||
uwe: uw::_Unwind_Exception,
|
||||
|
@ -35,7 +35,6 @@ pub unsafe fn panic(data: Box<Any + Send + 'static>) -> ! {
|
|||
|
||||
extern fn exception_cleanup(_unwind_code: uw::_Unwind_Reason_Code,
|
||||
exception: *mut uw::_Unwind_Exception) {
|
||||
rtdebug!("exception_cleanup()");
|
||||
unsafe {
|
||||
let _: Box<Exception> = Box::from_raw(exception as *mut Exception);
|
||||
}
|
||||
|
@ -44,7 +43,6 @@ pub unsafe fn panic(data: Box<Any + Send + 'static>) -> ! {
|
|||
|
||||
pub unsafe fn cleanup(ptr: *mut u8) -> Box<Any + Send + 'static> {
|
||||
let my_ep = ptr as *mut Exception;
|
||||
rtdebug!("caught {}", (*my_ep).uwe.exception_class);
|
||||
let cause = (*my_ep).cause.take();
|
||||
uw::_Unwind_DeleteException(ptr as *mut _);
|
||||
cause.unwrap()
|
||||
|
@ -80,7 +78,7 @@ fn rust_exception_class() -> uw::_Unwind_Exception_Class {
|
|||
not(all(windows, target_arch = "x86_64")),
|
||||
not(test)))]
|
||||
pub mod eabi {
|
||||
use rt::libunwind as uw;
|
||||
use sys_common::libunwind as uw;
|
||||
use libc::c_int;
|
||||
|
||||
extern {
|
||||
|
@ -136,7 +134,7 @@ pub mod eabi {
|
|||
|
||||
#[cfg(all(target_os = "ios", target_arch = "arm", not(test)))]
|
||||
pub mod eabi {
|
||||
use rt::libunwind as uw;
|
||||
use sys_common::libunwind as uw;
|
||||
use libc::c_int;
|
||||
|
||||
extern {
|
||||
|
@ -191,7 +189,7 @@ pub mod eabi {
|
|||
// but otherwise works the same.
|
||||
#[cfg(all(target_arch = "arm", not(target_os = "ios"), not(test)))]
|
||||
pub mod eabi {
|
||||
use rt::libunwind as uw;
|
||||
use sys_common::libunwind as uw;
|
||||
use libc::c_int;
|
||||
|
||||
extern {
|
|
@ -184,7 +184,6 @@ pub fn panicking() -> bool {
|
|||
#[no_mangle]
|
||||
#[allow(private_no_mangle_fns)]
|
||||
fn rust_panic(cause: Box<Any + Send + 'static>) -> ! {
|
||||
rtdebug!("begin_unwind()");
|
||||
unsafe {
|
||||
imp::panic(cause)
|
||||
}
|
||||
|
@ -288,7 +287,8 @@ fn begin_unwind_inner(msg: Box<Any + Send>,
|
|||
// have limited options. Currently our preference is to
|
||||
// just abort. In the future we may consider resuming
|
||||
// unwinding or otherwise exiting the thread cleanly.
|
||||
rterrln!("thread panicked while panicking. aborting.");
|
||||
super::util::dumb_print(format_args!("thread panicked while panicking. \
|
||||
aborting."));
|
||||
unsafe { intrinsics::abort() }
|
||||
}
|
||||
PANICKING.with(|s| s.set(true));
|
|
@ -135,10 +135,11 @@ fn rust_eh_personality() {
|
|||
// This function just takes a look at the current EXCEPTION_RECORD being thrown
|
||||
// to ensure that it's code is RUST_PANIC, which was set by the call to
|
||||
// `RaiseException` above in the `panic` function.
|
||||
#[no_mangle]
|
||||
#[lang = "msvc_try_filter"]
|
||||
pub extern fn __rust_try_filter(eh_ptrs: *mut EXCEPTION_POINTERS,
|
||||
_rbp: *mut u8) -> i32 {
|
||||
#[linkage = "external"]
|
||||
#[allow(private_no_mangle_fns)]
|
||||
extern fn __rust_try_filter(eh_ptrs: *mut EXCEPTION_POINTERS,
|
||||
_rbp: *mut u8) -> i32 {
|
||||
unsafe {
|
||||
((*(*eh_ptrs).ExceptionRecord).ExceptionCode == RUST_PANIC) as i32
|
||||
}
|
|
@ -18,7 +18,7 @@ use prelude::v1::*;
|
|||
|
||||
use any::Any;
|
||||
use self::EXCEPTION_DISPOSITION::*;
|
||||
use rt::dwarf::eh;
|
||||
use sys_common::dwarf::eh;
|
||||
use core::mem;
|
||||
use core::ptr;
|
||||
use libc::{c_void, c_ulonglong, DWORD, LPVOID};
|
||||
|
@ -114,7 +114,6 @@ struct PanicData {
|
|||
pub unsafe fn panic(data: Box<Any + Send + 'static>) -> ! {
|
||||
let panic_ctx = Box::new(PanicData { data: data });
|
||||
let params = [Box::into_raw(panic_ctx) as ULONG_PTR];
|
||||
rtdebug!("panic: ctx={:X}", params[0]);
|
||||
RaiseException(RUST_PANIC,
|
||||
EXCEPTION_NONCONTINUABLE,
|
||||
params.len() as DWORD,
|
||||
|
@ -123,7 +122,6 @@ pub unsafe fn panic(data: Box<Any + Send + 'static>) -> ! {
|
|||
}
|
||||
|
||||
pub unsafe fn cleanup(ptr: *mut u8) -> Box<Any + Send + 'static> {
|
||||
rtdebug!("cleanup: ctx={:X}", ptr as usize);
|
||||
let panic_ctx = Box::from_raw(ptr as *mut PanicData);
|
||||
return panic_ctx.data;
|
||||
}
|
||||
|
@ -174,15 +172,10 @@ unsafe extern fn rust_eh_personality(
|
|||
{
|
||||
let er = &*exceptionRecord;
|
||||
let dc = &*dispatcherContext;
|
||||
rtdebug!("rust_eh_personality: code={:X}, flags={:X}, frame={:X}, ip={:X}",
|
||||
er.ExceptionCode, er.ExceptionFlags,
|
||||
establisherFrame as usize, dc.ControlPc as usize);
|
||||
|
||||
if er.ExceptionFlags & EXCEPTION_UNWIND == 0 { // we are in the dispatch phase
|
||||
if er.ExceptionCode == RUST_PANIC {
|
||||
if let Some(lpad) = find_landing_pad(dc) {
|
||||
rtdebug!("unwinding to landing pad {:X}", lpad);
|
||||
|
||||
RtlUnwindEx(establisherFrame,
|
||||
lpad as LPVOID,
|
||||
exceptionRecord,
|
||||
|
@ -206,7 +199,6 @@ unsafe extern fn rust_eh_personality(
|
|||
#[lang = "eh_unwind_resume"]
|
||||
#[cfg(not(test))]
|
||||
unsafe extern fn rust_eh_unwind_resume(panic_ctx: LPVOID) {
|
||||
rtdebug!("rust_eh_unwind_resume: ctx={:X}", panic_ctx as usize);
|
||||
let params = [panic_ctx as ULONG_PTR];
|
||||
RaiseException(RUST_PANIC,
|
||||
EXCEPTION_NONCONTINUABLE,
|
|
@ -8,13 +8,13 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use io::prelude::*;
|
||||
|
||||
use env;
|
||||
use fmt;
|
||||
use intrinsics;
|
||||
use io::prelude::*;
|
||||
use sync::atomic::{self, Ordering};
|
||||
use sys::stdio::Stderr;
|
||||
use thread;
|
||||
|
||||
pub fn min_stack() -> usize {
|
||||
static MIN: atomic::AtomicUsize = atomic::AtomicUsize::new(0);
|
||||
|
@ -30,24 +30,17 @@ pub fn min_stack() -> usize {
|
|||
amt
|
||||
}
|
||||
|
||||
// Indicates whether we should perform expensive sanity checks, including rtassert!
|
||||
//
|
||||
// FIXME: Once the runtime matures remove the `true` below to turn off rtassert,
|
||||
// etc.
|
||||
pub const ENFORCE_SANITY: bool = true || !cfg!(rtopt) || cfg!(rtdebug) ||
|
||||
cfg!(rtassert);
|
||||
|
||||
pub fn dumb_print(args: fmt::Arguments) {
|
||||
let _ = Stderr::new().map(|mut stderr| stderr.write_fmt(args));
|
||||
}
|
||||
|
||||
pub fn abort(args: fmt::Arguments) -> ! {
|
||||
rterrln!("fatal runtime error: {}", args);
|
||||
dumb_print(format_args!("fatal runtime error: {}", args));
|
||||
unsafe { intrinsics::abort(); }
|
||||
}
|
||||
|
||||
#[allow(dead_code)] // stack overflow detection not enabled on all platforms
|
||||
pub unsafe fn report_overflow() {
|
||||
use thread;
|
||||
rterrln!("\nthread '{}' has overflowed its stack",
|
||||
thread::current().name().unwrap_or("<unknown>"));
|
||||
dumb_print(format_args!("\nthread '{}' has overflowed its stack",
|
||||
thread::current().name().unwrap_or("<unknown>")));
|
||||
}
|
|
@ -12,6 +12,7 @@
|
|||
#![allow(non_camel_case_types)]
|
||||
|
||||
use io::{self, ErrorKind};
|
||||
use libc::funcs::posix01::signal::signal;
|
||||
use libc;
|
||||
use num::One;
|
||||
use ops::Neg;
|
||||
|
@ -47,6 +48,19 @@ pub mod thread_local;
|
|||
pub mod time;
|
||||
pub mod stdio;
|
||||
|
||||
pub fn init() {
|
||||
// By default, some platforms will send a *signal* when a EPIPE error
|
||||
// would otherwise be delivered. This runtime doesn't install a SIGPIPE
|
||||
// handler, causing it to kill the program, which isn't exactly what we
|
||||
// want!
|
||||
//
|
||||
// Hence, we set SIGPIPE to ignore when the program starts up in order
|
||||
// to prevent this problem.
|
||||
unsafe {
|
||||
assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != !0);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decode_error_kind(errno: i32) -> ErrorKind {
|
||||
match errno as libc::c_int {
|
||||
libc::ECONNREFUSED => ErrorKind::ConnectionRefused,
|
||||
|
|
|
@ -358,8 +358,8 @@ pub fn args() -> Args {
|
|||
target_os = "netbsd",
|
||||
target_os = "openbsd"))]
|
||||
pub fn args() -> Args {
|
||||
use rt;
|
||||
let bytes = rt::args::clone().unwrap_or(Vec::new());
|
||||
use sys_common;
|
||||
let bytes = sys_common::args::clone().unwrap_or(Vec::new());
|
||||
let v: Vec<OsString> = bytes.into_iter().map(|v| {
|
||||
OsStringExt::from_vec(v)
|
||||
}).collect();
|
||||
|
|
|
@ -38,7 +38,7 @@ impl Drop for Handler {
|
|||
target_os = "openbsd"))]
|
||||
mod imp {
|
||||
use super::Handler;
|
||||
use rt::util::report_overflow;
|
||||
use sys_common::util::report_overflow;
|
||||
use mem;
|
||||
use ptr;
|
||||
use sys::c::{siginfo, sigaction, SIGBUS, SIG_DFL,
|
||||
|
|
|
@ -43,6 +43,8 @@ pub mod thread_local;
|
|||
pub mod time;
|
||||
pub mod stdio;
|
||||
|
||||
pub fn init() {}
|
||||
|
||||
pub fn decode_error_kind(errno: i32) -> ErrorKind {
|
||||
match errno as libc::c_int {
|
||||
libc::ERROR_ACCESS_DENIED => ErrorKind::PermissionDenied,
|
||||
|
|
|
@ -16,11 +16,10 @@ use net::SocketAddr;
|
|||
use num::One;
|
||||
use ops::Neg;
|
||||
use ptr;
|
||||
use rt;
|
||||
use sync::Once;
|
||||
use sys;
|
||||
use sys::c;
|
||||
use sys_common::{AsInner, FromInner, IntoInner};
|
||||
use sys_common::{self, AsInner, FromInner, IntoInner};
|
||||
use sys_common::net::{setsockopt, getsockopt};
|
||||
use time::Duration;
|
||||
|
||||
|
@ -39,7 +38,7 @@ pub fn init() {
|
|||
&mut data);
|
||||
assert_eq!(ret, 0);
|
||||
|
||||
let _ = rt::at_exit(|| { c::WSACleanup(); });
|
||||
let _ = sys_common::at_exit(|| { c::WSACleanup(); });
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
// except according to those terms.
|
||||
|
||||
use libc::{self, LONG};
|
||||
use rt::util::report_overflow;
|
||||
use sys_common::util::report_overflow;
|
||||
use sys::c;
|
||||
|
||||
pub struct Handler;
|
||||
|
|
|
@ -13,7 +13,7 @@ use prelude::v1::*;
|
|||
use libc::types::os::arch::extra::{DWORD, LPVOID, BOOL};
|
||||
|
||||
use ptr;
|
||||
use rt;
|
||||
use sys_common;
|
||||
use sys_common::mutex::Mutex;
|
||||
|
||||
pub type Key = DWORD;
|
||||
|
@ -133,7 +133,7 @@ unsafe fn init_dtors() {
|
|||
|
||||
let dtors = box Vec::<(Key, Dtor)>::new();
|
||||
|
||||
let res = rt::at_exit(move|| {
|
||||
let res = sys_common::at_exit(move|| {
|
||||
DTOR_LOCK.lock();
|
||||
let dtors = DTORS;
|
||||
DTORS = 1 as *mut _;
|
||||
|
|
|
@ -167,10 +167,11 @@ use any::Any;
|
|||
use cell::UnsafeCell;
|
||||
use fmt;
|
||||
use io;
|
||||
use rt::{self, unwind};
|
||||
use sync::{Mutex, Condvar, Arc};
|
||||
use sys::thread as imp;
|
||||
use sys_common::thread_info;
|
||||
use sys_common::unwind;
|
||||
use sys_common::util;
|
||||
use time::Duration;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -260,7 +261,7 @@ impl Builder {
|
|||
-> io::Result<JoinInner<T>> {
|
||||
let Builder { name, stack_size } = self;
|
||||
|
||||
let stack_size = stack_size.unwrap_or(rt::min_stack());
|
||||
let stack_size = stack_size.unwrap_or(util::min_stack());
|
||||
|
||||
let my_thread = Thread::new(name);
|
||||
let their_thread = my_thread.clone();
|
||||
|
@ -383,7 +384,7 @@ pub fn catch_panic<F, R>(f: F) -> Result<R>
|
|||
let mut result = None;
|
||||
unsafe {
|
||||
let result = &mut result;
|
||||
try!(::rt::unwind::try(move || *result = Some(f())))
|
||||
try!(unwind::try(move || *result = Some(f())))
|
||||
}
|
||||
Ok(result.unwrap())
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue