Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustc: Switch defaults from libgreen to libnative #12833

Merged
merged 3 commits into from Mar 22, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/compiletest/compiletest.rs
Expand Up @@ -19,6 +19,8 @@ extern crate test;
extern crate getopts;
#[phase(link, syntax)]
extern crate log;
extern crate green;
extern crate rustuv;

use std::os;
use std::io;
Expand All @@ -41,6 +43,9 @@ pub mod runtest;
pub mod common;
pub mod errors;

#[start]
fn start(argc: int, argv: **u8) -> int { green::start(argc, argv, main) }

pub fn main() {
let args = os::args();
let config = parse_config(args.move_iter().collect());
Expand Down
8 changes: 6 additions & 2 deletions src/driver/driver.rs
Expand Up @@ -8,15 +8,19 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[no_uv];
#[no_uv]; // remove this after stage0
#[allow(attribute_usage)]; // remove this after stage0
extern crate native; // remove this after stage0

#[cfg(rustdoc)]
extern crate this = "rustdoc";

#[cfg(rustc)]
extern crate this = "rustc";

extern crate native;
#[cfg(not(stage0))]
fn main() { this::main() }

#[cfg(stage0)]
#[start]
fn start(argc: int, argv: **u8) -> int { native::start(argc, argv, this::main) }
2 changes: 1 addition & 1 deletion src/libgreen/lib.rs
Expand Up @@ -209,7 +209,7 @@ pub mod stack;
pub mod task;

#[lang = "start"]
#[cfg(not(test))]
#[cfg(not(test), stage0)]
pub fn lang_start(main: *u8, argc: int, argv: **u8) -> int {
use std::cast;
start(argc, argv, proc() {
Expand Down
18 changes: 17 additions & 1 deletion src/libnative/lib.rs
Expand Up @@ -58,6 +58,7 @@

use std::os;
use std::rt;
use std::str;

pub mod io;
pub mod task;
Expand All @@ -68,6 +69,16 @@ static OS_DEFAULT_STACK_ESTIMATE: uint = 1 << 20;
#[cfg(unix, not(android))]
static OS_DEFAULT_STACK_ESTIMATE: uint = 2 * (1 << 20);

#[lang = "start"]
#[cfg(not(test), not(stage0))]
pub fn lang_start(main: *u8, argc: int, argv: **u8) -> int {
use std::cast;
start(argc, argv, proc() {
let main: extern "Rust" fn() = unsafe { cast::transmute(main) };
main();
})
}

/// Executes the given procedure after initializing the runtime with the given
/// argc/argv.
///
Expand All @@ -90,7 +101,12 @@ pub fn start(argc: int, argv: **u8, main: proc()) -> int {
rt::init(argc, argv);
let mut exit_code = None;
let mut main = Some(main);
let t = task::new((my_stack_bottom, my_stack_top)).run(|| {
let mut task = task::new((my_stack_bottom, my_stack_top));
task.name = Some(str::Slice("<main>"));
let t = task.run(|| {
unsafe {
rt::stack::record_stack_bounds(my_stack_bottom, my_stack_top);
}
exit_code = Some(run(main.take_unwrap()));
});
drop(t);
Expand Down
246 changes: 150 additions & 96 deletions src/librand/os.rs
Expand Up @@ -11,124 +11,178 @@
//! Interfaces to the operating system provided random number
//! generators.

use Rng;
pub use self::imp::OSRng;

#[cfg(unix)]
use reader::ReaderRng;
#[cfg(unix)]
use std::io::File;

#[cfg(windows)]
use std::cast;
#[cfg(windows)]
use std::libc::{c_long, DWORD, BYTE};
#[cfg(windows)]
type HCRYPTPROV = c_long;
// the extern functions imported from the runtime on Windows are
// implemented so that they either succeed or abort(), so we can just
// assume they work when we call them.

/// A random number generator that retrieves randomness straight from
/// the operating system. Platform sources:
///
/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
/// `/dev/urandom`.
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
/// service provider with the `PROV_RSA_FULL` type.
///
/// This does not block.
#[cfg(unix)]
pub struct OSRng {
priv inner: ReaderRng<File>
}
/// A random number generator that retrieves randomness straight from
/// the operating system. Platform sources:
///
/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
/// `/dev/urandom`.
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
/// service provider with the `PROV_RSA_FULL` type.
///
/// This does not block.
#[cfg(windows)]
pub struct OSRng {
priv hcryptprov: HCRYPTPROV
}

impl OSRng {
/// Create a new `OSRng`.
mod imp {
use Rng;
use reader::ReaderRng;
use std::io::File;

/// A random number generator that retrieves randomness straight from
/// the operating system. Platform sources:
///
/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
/// `/dev/urandom`.
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
/// service provider with the `PROV_RSA_FULL` type.
///
/// This does not block.
#[cfg(unix)]
pub fn new() -> OSRng {
let reader = File::open(&Path::new("/dev/urandom"));
let reader = reader.ok().expect("Error opening /dev/urandom");
let reader_rng = ReaderRng::new(reader);

OSRng { inner: reader_rng }
pub struct OSRng {
priv inner: ReaderRng<File>
}

/// Create a new `OSRng`.
#[cfg(windows)]
pub fn new() -> OSRng {
extern { fn rust_win32_rand_acquire(phProv: *mut HCRYPTPROV); }
impl OSRng {
/// Create a new `OSRng`.
pub fn new() -> OSRng {
let reader = File::open(&Path::new("/dev/urandom"));
let reader = reader.ok().expect("Error opening /dev/urandom");
let reader_rng = ReaderRng::new(reader);

let mut hcp = 0;
unsafe {rust_win32_rand_acquire(&mut hcp)};

OSRng { hcryptprov: hcp }
OSRng { inner: reader_rng }
}
}
}

#[cfg(unix)]
impl Rng for OSRng {
fn next_u32(&mut self) -> u32 {
self.inner.next_u32()
}
fn next_u64(&mut self) -> u64 {
self.inner.next_u64()
}
fn fill_bytes(&mut self, v: &mut [u8]) {
self.inner.fill_bytes(v)
impl Rng for OSRng {
fn next_u32(&mut self) -> u32 {
self.inner.next_u32()
}
fn next_u64(&mut self) -> u64 {
self.inner.next_u64()
}
fn fill_bytes(&mut self, v: &mut [u8]) {
self.inner.fill_bytes(v)
}
}
}

#[cfg(windows)]
impl Rng for OSRng {
fn next_u32(&mut self) -> u32 {
let mut v = [0u8, .. 4];
self.fill_bytes(v);
unsafe { cast::transmute(v) }
}
fn next_u64(&mut self) -> u64 {
let mut v = [0u8, .. 8];
self.fill_bytes(v);
unsafe { cast::transmute(v) }
mod imp {
use Rng;
use std::cast;
use std::libc::{c_ulong, DWORD, BYTE, LPCSTR, BOOL};
use std::os;
use std::rt::stack;

type HCRYPTPROV = c_ulong;

/// A random number generator that retrieves randomness straight from
/// the operating system. Platform sources:
///
/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
/// `/dev/urandom`.
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
/// service provider with the `PROV_RSA_FULL` type.
///
/// This does not block.
pub struct OSRng {
priv hcryptprov: HCRYPTPROV
}
fn fill_bytes(&mut self, v: &mut [u8]) {
extern {
fn rust_win32_rand_gen(hProv: HCRYPTPROV, dwLen: DWORD,
pbBuffer: *mut BYTE);
}

unsafe {rust_win32_rand_gen(self.hcryptprov, v.len() as DWORD, v.as_mut_ptr())}
static PROV_RSA_FULL: DWORD = 1;
static CRYPT_SILENT: DWORD = 64;
static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;
static NTE_BAD_SIGNATURE: DWORD = 0x80090006;

extern "system" {
fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
pszContainer: LPCSTR,
pszProvider: LPCSTR,
dwProvType: DWORD,
dwFlags: DWORD) -> BOOL;
fn CryptGenRandom(hProv: HCRYPTPROV,
dwLen: DWORD,
pbBuffer: *mut BYTE) -> BOOL;
fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
}
}

impl Drop for OSRng {
#[cfg(unix)]
fn drop(&mut self) {
// ensure that OSRng is not implicitly copyable on all
// platforms, for consistency.
impl OSRng {
/// Create a new `OSRng`.
pub fn new() -> OSRng {
let mut hcp = 0;
let mut ret = unsafe {
CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
};

// It turns out that if we can't acquire a context with the
// NTE_BAD_SIGNATURE error code, the documentation states:
//
// The provider DLL signature could not be verified. Either the
// DLL or the digital signature has been tampered with.
//
// Sounds fishy, no? As it turns out, our signature can be bad
// because our Thread Information Block (TIB) isn't exactly what it
// expects. As to why, I have no idea. The only data we store in the
// TIB is the stack limit for each thread, but apparently that's
// enough to make the signature valid.
//
// Furthermore, this error only happens the *first* time we call
// CryptAcquireContext, so we don't have to worry about future
// calls.
//
// Anyway, the fix employed here is that if we see this error, we
// pray that we're not close to the end of the stack, temporarily
// set the stack limit to 0 (what the TIB originally was), acquire a
// context, and then reset the stack limit.
//
// Again, I'm not sure why this is the fix, nor why we're getting
// this error. All I can say is that this seems to allow libnative
// to progress where it otherwise would be hindered. Who knew?
if ret == 0 && os::errno() as DWORD == NTE_BAD_SIGNATURE {
unsafe {
let limit = stack::get_sp_limit();
stack::record_sp_limit(0);
ret = CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
stack::record_sp_limit(limit);
}
}

if ret == 0 {
fail!("couldn't create context: {}", os::last_os_error());
}
OSRng { hcryptprov: hcp }
}
}

#[cfg(windows)]
fn drop(&mut self) {
extern { fn rust_win32_rand_release(hProv: HCRYPTPROV); }
impl Rng for OSRng {
fn next_u32(&mut self) -> u32 {
let mut v = [0u8, .. 4];
self.fill_bytes(v);
unsafe { cast::transmute(v) }
}
fn next_u64(&mut self) -> u64 {
let mut v = [0u8, .. 8];
self.fill_bytes(v);
unsafe { cast::transmute(v) }
}
fn fill_bytes(&mut self, v: &mut [u8]) {
let ret = unsafe {
CryptGenRandom(self.hcryptprov, v.len() as DWORD,
v.as_mut_ptr())
};
if ret == 0 {
fail!("couldn't generate random bytes: {}", os::last_os_error());
}
}
}

unsafe {rust_win32_rand_release(self.hcryptprov)}
impl Drop for OSRng {
fn drop(&mut self) {
let ret = unsafe {
CryptReleaseContext(self.hcryptprov, 0)
};
if ret == 0 {
fail!("couldn't release context: {}", os::last_os_error());
}
}
}
}


#[cfg(test)]
mod test {
use super::OSRng;
Expand Down
18 changes: 5 additions & 13 deletions src/librustc/front/std_inject.rs
Expand Up @@ -46,8 +46,8 @@ fn use_std(krate: &ast::Crate) -> bool {
!attr::contains_name(krate.attrs.as_slice(), "no_std")
}

fn use_uv(krate: &ast::Crate) -> bool {
!attr::contains_name(krate.attrs.as_slice(), "no_uv")
fn use_start(krate: &ast::Crate) -> bool {
!attr::contains_name(krate.attrs.as_slice(), "no_start")
}

fn no_prelude(attrs: &[ast::Attribute]) -> bool {
Expand Down Expand Up @@ -87,18 +87,10 @@ impl<'a> fold::Folder for StandardLibraryInjector<'a> {
span: DUMMY_SP
});

if use_uv(&krate) && !self.sess.building_library.get() {
if use_start(&krate) && !self.sess.building_library.get() {
vis.push(ast::ViewItem {
node: ast::ViewItemExternCrate(token::str_to_ident("green"),
with_version("green"),
ast::DUMMY_NODE_ID),
attrs: Vec::new(),
vis: ast::Inherited,
span: DUMMY_SP
});
vis.push(ast::ViewItem {
node: ast::ViewItemExternCrate(token::str_to_ident("rustuv"),
with_version("rustuv"),
node: ast::ViewItemExternCrate(token::str_to_ident("native"),
with_version("native"),
ast::DUMMY_NODE_ID),
attrs: Vec::new(),
vis: ast::Inherited,
Expand Down