Skip to content

Commit e4136bd

Browse files
committed
auto merge of #10662 : alexcrichton/rust/thread-detach, r=pcwalton
This has one commit from a separate pull request (because these commits depend on that one), but otherwise the extra details can be found in the commit messages. The `rt::thread` module has been generally cleaned up for everyday safe usage (and it's a bug if it's not safe).
2 parents a6fc577 + 5d6dbf3 commit e4136bd

File tree

7 files changed

+208
-75
lines changed

7 files changed

+208
-75
lines changed

src/libstd/rt/args.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ pub unsafe fn init(argc: int, argv: **u8) { imp::init(argc, argv) }
3232
pub unsafe fn init(argc: int, argv: **u8) { realargs::init(argc, argv) }
3333

3434
/// One-time global cleanup.
35-
#[cfg(not(test))] pub fn cleanup() { imp::cleanup() }
36-
#[cfg(test)] pub fn cleanup() { realargs::cleanup() }
35+
#[cfg(not(test))] pub unsafe fn cleanup() { imp::cleanup() }
36+
#[cfg(test)] pub unsafe fn cleanup() { realargs::cleanup() }
3737

3838
/// Take the global arguments from global storage.
3939
#[cfg(not(test))] pub fn take() -> Option<~[~str]> { imp::take() }
@@ -74,14 +74,16 @@ mod imp {
7474
use vec;
7575

7676
static mut global_args_ptr: uint = 0;
77+
static mut lock: Mutex = MUTEX_INIT;
7778

7879
pub unsafe fn init(argc: int, argv: **u8) {
7980
let args = load_argc_and_argv(argc, argv);
8081
put(args);
8182
}
8283

83-
pub fn cleanup() {
84+
pub unsafe fn cleanup() {
8485
rtassert!(take().is_some());
86+
lock.destroy();
8587
}
8688

8789
pub fn take() -> Option<~[~str]> {
@@ -108,7 +110,6 @@ mod imp {
108110
}
109111

110112
fn with_lock<T>(f: || -> T) -> T {
111-
static mut lock: Mutex = MUTEX_INIT;
112113
(|| {
113114
unsafe {
114115
lock.lock();

src/libstd/rt/local_ptr.rs

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,27 +41,49 @@ pub static mut RT_TLS_PTR: *mut c_void = 0 as *mut c_void;
4141
#[cfg(stage0)]
4242
#[cfg(windows)]
4343
static mut RT_TLS_KEY: tls::Key = -1;
44+
#[cfg(stage0)]
45+
#[cfg(windows)]
46+
static mut tls_lock: Mutex = MUTEX_INIT;
47+
static mut tls_initialized: bool = false;
4448

4549
/// Initialize the TLS key. Other ops will fail if this isn't executed first.
4650
#[inline(never)]
4751
#[cfg(stage0)]
4852
#[cfg(windows)]
4953
pub fn init_tls_key() {
50-
static mut lock: Mutex = MUTEX_INIT;
51-
static mut initialized: bool = false;
52-
5354
unsafe {
54-
lock.lock();
55-
if !initialized {
55+
tls_lock.lock();
56+
if !tls_initialized {
5657
tls::create(&mut RT_TLS_KEY);
57-
initialized = true;
58+
tls_initialized = true;
5859
}
59-
lock.unlock();
60+
tls_lock.unlock();
6061
}
6162
}
6263

6364
#[cfg(not(stage0), not(windows))]
64-
pub fn init_tls_key() {}
65+
pub fn init_tls_key() {
66+
unsafe {
67+
tls_initialized = true;
68+
}
69+
}
70+
71+
#[cfg(windows)]
72+
pub unsafe fn cleanup() {
73+
// No real use to acquiring a lock around these operations. All we're
74+
// going to do is destroy the lock anyway which races locking itself. This
75+
// is why the whole function is labeled as 'unsafe'
76+
assert!(tls_initialized);
77+
tls::destroy(RT_TLS_KEY);
78+
tls_lock.destroy();
79+
tls_initialized = false;
80+
}
81+
82+
#[cfg(not(windows))]
83+
pub unsafe fn cleanup() {
84+
assert!(tls_initialized);
85+
tls_initialized = false;
86+
}
6587

6688
/// Give a pointer to thread-local storage.
6789
///

src/libstd/rt/mod.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,8 @@ pub fn start(argc: int, argv: **u8, main: proc()) -> int {
215215

216216
init(argc, argv);
217217
let exit_code = run(main);
218-
cleanup();
218+
// unsafe is ok b/c we're sure that the runtime is gone
219+
unsafe { cleanup(); }
219220

220221
return exit_code;
221222
}
@@ -228,7 +229,8 @@ pub fn start(argc: int, argv: **u8, main: proc()) -> int {
228229
pub fn start_on_main_thread(argc: int, argv: **u8, main: proc()) -> int {
229230
init(argc, argv);
230231
let exit_code = run_on_main_thread(main);
231-
cleanup();
232+
// unsafe is ok b/c we're sure that the runtime is gone
233+
unsafe { cleanup(); }
232234

233235
return exit_code;
234236
}
@@ -249,8 +251,17 @@ pub fn init(argc: int, argv: **u8) {
249251
}
250252

251253
/// One-time runtime cleanup.
252-
pub fn cleanup() {
254+
///
255+
/// This function is unsafe because it performs no checks to ensure that the
256+
/// runtime has completely ceased running. It is the responsibility of the
257+
/// caller to ensure that the runtime is entirely shut down and nothing will be
258+
/// poking around at the internal components.
259+
///
260+
/// Invoking cleanup while portions of the runtime are still in use may cause
261+
/// undefined behavior.
262+
pub unsafe fn cleanup() {
253263
args::cleanup();
264+
local_ptr::cleanup();
254265
}
255266

256267
/// Execute the main function in a scheduler.

src/libstd/rt/test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ pub fn spawntask_try(f: proc()) -> Result<(),()> {
336336
}
337337

338338
/// Spawn a new task in a new scheduler and return a thread handle.
339-
pub fn spawntask_thread(f: proc()) -> Thread {
339+
pub fn spawntask_thread(f: proc()) -> Thread<()> {
340340

341341
let f = Cell::new(f);
342342

0 commit comments

Comments
 (0)