Skip to content

Commit bbf8cdc

Browse files
committed
auto merge of #12833 : alexcrichton/rust/libnative, r=brson
The compiler will no longer inject libgreen as the default runtime for rust programs, this commit switches it over to libnative by default. Now that libnative has baked for some time, it is ready enough to start getting more serious usage as the default runtime for rustc generated binaries. We've found that there isn't really a correct decision in choosing a 1:1 or M:N runtime as a default for all applications, but it seems that a larger number of programs today would work more reasonably with a native default rather than a green default. With this commit come a number of bugfixes: * The main native task is now named `<main>` * The main native task has the stack bounds set up properly * #[no_uv] was renamed to #[no_start] * The core-run-destroy test was rewritten for both libnative and libgreen and one of the tests was modified to be more robust. * The process-detach test was locked to libgreen because it uses signal handling
2 parents 3e3a3cf + e7c4fb6 commit bbf8cdc

File tree

17 files changed

+280
-239
lines changed

17 files changed

+280
-239
lines changed

src/compiletest/compiletest.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ extern crate test;
1919
extern crate getopts;
2020
#[phase(link, syntax)]
2121
extern crate log;
22+
extern crate green;
23+
extern crate rustuv;
2224

2325
use std::os;
2426
use std::io;
@@ -41,6 +43,9 @@ pub mod runtest;
4143
pub mod common;
4244
pub mod errors;
4345

46+
#[start]
47+
fn start(argc: int, argv: **u8) -> int { green::start(argc, argv, main) }
48+
4449
pub fn main() {
4550
let args = os::args();
4651
let config = parse_config(args.move_iter().collect());

src/driver/driver.rs

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

11-
#[no_uv];
11+
#[no_uv]; // remove this after stage0
12+
#[allow(attribute_usage)]; // remove this after stage0
13+
extern crate native; // remove this after stage0
1214

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

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

19-
extern crate native;
21+
#[cfg(not(stage0))]
22+
fn main() { this::main() }
2023

24+
#[cfg(stage0)]
2125
#[start]
2226
fn start(argc: int, argv: **u8) -> int { native::start(argc, argv, this::main) }

src/libgreen/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ pub mod stack;
209209
pub mod task;
210210

211211
#[lang = "start"]
212-
#[cfg(not(test))]
212+
#[cfg(not(test), stage0)]
213213
pub fn lang_start(main: *u8, argc: int, argv: **u8) -> int {
214214
use std::cast;
215215
start(argc, argv, proc() {

src/libnative/lib.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858

5959
use std::os;
6060
use std::rt;
61+
use std::str;
6162

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

72+
#[lang = "start"]
73+
#[cfg(not(test), not(stage0))]
74+
pub fn lang_start(main: *u8, argc: int, argv: **u8) -> int {
75+
use std::cast;
76+
start(argc, argv, proc() {
77+
let main: extern "Rust" fn() = unsafe { cast::transmute(main) };
78+
main();
79+
})
80+
}
81+
7182
/// Executes the given procedure after initializing the runtime with the given
7283
/// argc/argv.
7384
///
@@ -90,7 +101,12 @@ pub fn start(argc: int, argv: **u8, main: proc()) -> int {
90101
rt::init(argc, argv);
91102
let mut exit_code = None;
92103
let mut main = Some(main);
93-
let t = task::new((my_stack_bottom, my_stack_top)).run(|| {
104+
let mut task = task::new((my_stack_bottom, my_stack_top));
105+
task.name = Some(str::Slice("<main>"));
106+
let t = task.run(|| {
107+
unsafe {
108+
rt::stack::record_stack_bounds(my_stack_bottom, my_stack_top);
109+
}
94110
exit_code = Some(run(main.take_unwrap()));
95111
});
96112
drop(t);

src/librand/os.rs

Lines changed: 150 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -11,124 +11,178 @@
1111
//! Interfaces to the operating system provided random number
1212
//! generators.
1313
14-
use Rng;
14+
pub use self::imp::OSRng;
1515

1616
#[cfg(unix)]
17-
use reader::ReaderRng;
18-
#[cfg(unix)]
19-
use std::io::File;
20-
21-
#[cfg(windows)]
22-
use std::cast;
23-
#[cfg(windows)]
24-
use std::libc::{c_long, DWORD, BYTE};
25-
#[cfg(windows)]
26-
type HCRYPTPROV = c_long;
27-
// the extern functions imported from the runtime on Windows are
28-
// implemented so that they either succeed or abort(), so we can just
29-
// assume they work when we call them.
30-
31-
/// A random number generator that retrieves randomness straight from
32-
/// the operating system. Platform sources:
33-
///
34-
/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
35-
/// `/dev/urandom`.
36-
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
37-
/// service provider with the `PROV_RSA_FULL` type.
38-
///
39-
/// This does not block.
40-
#[cfg(unix)]
41-
pub struct OSRng {
42-
priv inner: ReaderRng<File>
43-
}
44-
/// A random number generator that retrieves randomness straight from
45-
/// the operating system. Platform sources:
46-
///
47-
/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
48-
/// `/dev/urandom`.
49-
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
50-
/// service provider with the `PROV_RSA_FULL` type.
51-
///
52-
/// This does not block.
53-
#[cfg(windows)]
54-
pub struct OSRng {
55-
priv hcryptprov: HCRYPTPROV
56-
}
57-
58-
impl OSRng {
59-
/// Create a new `OSRng`.
17+
mod imp {
18+
use Rng;
19+
use reader::ReaderRng;
20+
use std::io::File;
21+
22+
/// A random number generator that retrieves randomness straight from
23+
/// the operating system. Platform sources:
24+
///
25+
/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
26+
/// `/dev/urandom`.
27+
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
28+
/// service provider with the `PROV_RSA_FULL` type.
29+
///
30+
/// This does not block.
6031
#[cfg(unix)]
61-
pub fn new() -> OSRng {
62-
let reader = File::open(&Path::new("/dev/urandom"));
63-
let reader = reader.ok().expect("Error opening /dev/urandom");
64-
let reader_rng = ReaderRng::new(reader);
65-
66-
OSRng { inner: reader_rng }
32+
pub struct OSRng {
33+
priv inner: ReaderRng<File>
6734
}
6835

69-
/// Create a new `OSRng`.
70-
#[cfg(windows)]
71-
pub fn new() -> OSRng {
72-
extern { fn rust_win32_rand_acquire(phProv: *mut HCRYPTPROV); }
36+
impl OSRng {
37+
/// Create a new `OSRng`.
38+
pub fn new() -> OSRng {
39+
let reader = File::open(&Path::new("/dev/urandom"));
40+
let reader = reader.ok().expect("Error opening /dev/urandom");
41+
let reader_rng = ReaderRng::new(reader);
7342

74-
let mut hcp = 0;
75-
unsafe {rust_win32_rand_acquire(&mut hcp)};
76-
77-
OSRng { hcryptprov: hcp }
43+
OSRng { inner: reader_rng }
44+
}
7845
}
79-
}
8046

81-
#[cfg(unix)]
82-
impl Rng for OSRng {
83-
fn next_u32(&mut self) -> u32 {
84-
self.inner.next_u32()
85-
}
86-
fn next_u64(&mut self) -> u64 {
87-
self.inner.next_u64()
88-
}
89-
fn fill_bytes(&mut self, v: &mut [u8]) {
90-
self.inner.fill_bytes(v)
47+
impl Rng for OSRng {
48+
fn next_u32(&mut self) -> u32 {
49+
self.inner.next_u32()
50+
}
51+
fn next_u64(&mut self) -> u64 {
52+
self.inner.next_u64()
53+
}
54+
fn fill_bytes(&mut self, v: &mut [u8]) {
55+
self.inner.fill_bytes(v)
56+
}
9157
}
9258
}
9359

9460
#[cfg(windows)]
95-
impl Rng for OSRng {
96-
fn next_u32(&mut self) -> u32 {
97-
let mut v = [0u8, .. 4];
98-
self.fill_bytes(v);
99-
unsafe { cast::transmute(v) }
100-
}
101-
fn next_u64(&mut self) -> u64 {
102-
let mut v = [0u8, .. 8];
103-
self.fill_bytes(v);
104-
unsafe { cast::transmute(v) }
61+
mod imp {
62+
use Rng;
63+
use std::cast;
64+
use std::libc::{c_ulong, DWORD, BYTE, LPCSTR, BOOL};
65+
use std::os;
66+
use std::rt::stack;
67+
68+
type HCRYPTPROV = c_ulong;
69+
70+
/// A random number generator that retrieves randomness straight from
71+
/// the operating system. Platform sources:
72+
///
73+
/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
74+
/// `/dev/urandom`.
75+
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
76+
/// service provider with the `PROV_RSA_FULL` type.
77+
///
78+
/// This does not block.
79+
pub struct OSRng {
80+
priv hcryptprov: HCRYPTPROV
10581
}
106-
fn fill_bytes(&mut self, v: &mut [u8]) {
107-
extern {
108-
fn rust_win32_rand_gen(hProv: HCRYPTPROV, dwLen: DWORD,
109-
pbBuffer: *mut BYTE);
110-
}
11182

112-
unsafe {rust_win32_rand_gen(self.hcryptprov, v.len() as DWORD, v.as_mut_ptr())}
83+
static PROV_RSA_FULL: DWORD = 1;
84+
static CRYPT_SILENT: DWORD = 64;
85+
static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;
86+
static NTE_BAD_SIGNATURE: DWORD = 0x80090006;
87+
88+
extern "system" {
89+
fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
90+
pszContainer: LPCSTR,
91+
pszProvider: LPCSTR,
92+
dwProvType: DWORD,
93+
dwFlags: DWORD) -> BOOL;
94+
fn CryptGenRandom(hProv: HCRYPTPROV,
95+
dwLen: DWORD,
96+
pbBuffer: *mut BYTE) -> BOOL;
97+
fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
11398
}
114-
}
11599

116-
impl Drop for OSRng {
117-
#[cfg(unix)]
118-
fn drop(&mut self) {
119-
// ensure that OSRng is not implicitly copyable on all
120-
// platforms, for consistency.
100+
impl OSRng {
101+
/// Create a new `OSRng`.
102+
pub fn new() -> OSRng {
103+
let mut hcp = 0;
104+
let mut ret = unsafe {
105+
CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
106+
PROV_RSA_FULL,
107+
CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
108+
};
109+
110+
// It turns out that if we can't acquire a context with the
111+
// NTE_BAD_SIGNATURE error code, the documentation states:
112+
//
113+
// The provider DLL signature could not be verified. Either the
114+
// DLL or the digital signature has been tampered with.
115+
//
116+
// Sounds fishy, no? As it turns out, our signature can be bad
117+
// because our Thread Information Block (TIB) isn't exactly what it
118+
// expects. As to why, I have no idea. The only data we store in the
119+
// TIB is the stack limit for each thread, but apparently that's
120+
// enough to make the signature valid.
121+
//
122+
// Furthermore, this error only happens the *first* time we call
123+
// CryptAcquireContext, so we don't have to worry about future
124+
// calls.
125+
//
126+
// Anyway, the fix employed here is that if we see this error, we
127+
// pray that we're not close to the end of the stack, temporarily
128+
// set the stack limit to 0 (what the TIB originally was), acquire a
129+
// context, and then reset the stack limit.
130+
//
131+
// Again, I'm not sure why this is the fix, nor why we're getting
132+
// this error. All I can say is that this seems to allow libnative
133+
// to progress where it otherwise would be hindered. Who knew?
134+
if ret == 0 && os::errno() as DWORD == NTE_BAD_SIGNATURE {
135+
unsafe {
136+
let limit = stack::get_sp_limit();
137+
stack::record_sp_limit(0);
138+
ret = CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
139+
PROV_RSA_FULL,
140+
CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
141+
stack::record_sp_limit(limit);
142+
}
143+
}
144+
145+
if ret == 0 {
146+
fail!("couldn't create context: {}", os::last_os_error());
147+
}
148+
OSRng { hcryptprov: hcp }
149+
}
121150
}
122151

123-
#[cfg(windows)]
124-
fn drop(&mut self) {
125-
extern { fn rust_win32_rand_release(hProv: HCRYPTPROV); }
152+
impl Rng for OSRng {
153+
fn next_u32(&mut self) -> u32 {
154+
let mut v = [0u8, .. 4];
155+
self.fill_bytes(v);
156+
unsafe { cast::transmute(v) }
157+
}
158+
fn next_u64(&mut self) -> u64 {
159+
let mut v = [0u8, .. 8];
160+
self.fill_bytes(v);
161+
unsafe { cast::transmute(v) }
162+
}
163+
fn fill_bytes(&mut self, v: &mut [u8]) {
164+
let ret = unsafe {
165+
CryptGenRandom(self.hcryptprov, v.len() as DWORD,
166+
v.as_mut_ptr())
167+
};
168+
if ret == 0 {
169+
fail!("couldn't generate random bytes: {}", os::last_os_error());
170+
}
171+
}
172+
}
126173

127-
unsafe {rust_win32_rand_release(self.hcryptprov)}
174+
impl Drop for OSRng {
175+
fn drop(&mut self) {
176+
let ret = unsafe {
177+
CryptReleaseContext(self.hcryptprov, 0)
178+
};
179+
if ret == 0 {
180+
fail!("couldn't release context: {}", os::last_os_error());
181+
}
182+
}
128183
}
129184
}
130185

131-
132186
#[cfg(test)]
133187
mod test {
134188
use super::OSRng;

src/librustc/front/std_inject.rs

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ fn use_std(krate: &ast::Crate) -> bool {
4646
!attr::contains_name(krate.attrs.as_slice(), "no_std")
4747
}
4848

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

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

90-
if use_uv(&krate) && !self.sess.building_library.get() {
90+
if use_start(&krate) && !self.sess.building_library.get() {
9191
vis.push(ast::ViewItem {
92-
node: ast::ViewItemExternCrate(token::str_to_ident("green"),
93-
with_version("green"),
94-
ast::DUMMY_NODE_ID),
95-
attrs: Vec::new(),
96-
vis: ast::Inherited,
97-
span: DUMMY_SP
98-
});
99-
vis.push(ast::ViewItem {
100-
node: ast::ViewItemExternCrate(token::str_to_ident("rustuv"),
101-
with_version("rustuv"),
92+
node: ast::ViewItemExternCrate(token::str_to_ident("native"),
93+
with_version("native"),
10294
ast::DUMMY_NODE_ID),
10395
attrs: Vec::new(),
10496
vis: ast::Inherited,

0 commit comments

Comments
 (0)