Skip to content

Commit 8a8ce7c

Browse files
committed
Revert "Revert "std: Re-enable at_exit()""
This reverts commit aec67c2.
1 parent 6354d60 commit 8a8ce7c

39 files changed

+200
-250
lines changed

src/liblog/lib.rs

+26-8
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ use std::mem;
181181
use std::os;
182182
use std::rt;
183183
use std::slice;
184-
use std::sync::{Once, ONCE_INIT};
184+
use std::sync::{Once, ONCE_INIT, StaticMutex, MUTEX_INIT};
185185

186186
use regex::Regex;
187187

@@ -199,6 +199,8 @@ pub const MAX_LOG_LEVEL: u32 = 255;
199199
/// The default logging level of a crate if no other is specified.
200200
const DEFAULT_LOG_LEVEL: u32 = 1;
201201

202+
static LOCK: StaticMutex = MUTEX_INIT;
203+
202204
/// An unsafe constant that is the maximum logging level of any module
203205
/// specified. This is the first line of defense to determining whether a
204206
/// logging statement should be run.
@@ -291,9 +293,18 @@ impl Drop for DefaultLogger {
291293
pub fn log(level: u32, loc: &'static LogLocation, args: fmt::Arguments) {
292294
// Test the literal string from args against the current filter, if there
293295
// is one.
294-
match unsafe { FILTER.as_ref() } {
295-
Some(filter) if !filter.is_match(&args.to_string()[]) => return,
296-
_ => {}
296+
unsafe {
297+
let _g = LOCK.lock();
298+
match FILTER as uint {
299+
0 => {}
300+
1 => panic!("cannot log after main thread has exited"),
301+
n => {
302+
let filter = mem::transmute::<_, &Regex>(n);
303+
if !filter.is_match(args.to_string().as_slice()) {
304+
return
305+
}
306+
}
307+
}
297308
}
298309

299310
// Completely remove the local logger from TLS in case anyone attempts to
@@ -375,9 +386,15 @@ pub fn mod_enabled(level: u32, module: &str) -> bool {
375386

376387
// This assertion should never get tripped unless we're in an at_exit
377388
// handler after logging has been torn down and a logging attempt was made.
378-
assert!(unsafe { !DIRECTIVES.is_null() });
379389

380-
enabled(level, module, unsafe { (*DIRECTIVES).iter() })
390+
let _g = LOCK.lock();
391+
unsafe {
392+
assert!(DIRECTIVES as uint != 0);
393+
assert!(DIRECTIVES as uint != 1,
394+
"cannot log after the main thread has exited");
395+
396+
enabled(level, module, (*DIRECTIVES).iter())
397+
}
381398
}
382399

383400
fn enabled(level: u32,
@@ -433,14 +450,15 @@ fn init() {
433450

434451
// Schedule the cleanup for the globals for when the runtime exits.
435452
rt::at_exit(move |:| {
453+
let _g = LOCK.lock();
436454
assert!(!DIRECTIVES.is_null());
437455
let _directives: Box<Vec<directive::LogDirective>> =
438456
mem::transmute(DIRECTIVES);
439-
DIRECTIVES = 0 as *const Vec<directive::LogDirective>;
457+
DIRECTIVES = 1 as *const Vec<directive::LogDirective>;
440458

441459
if !FILTER.is_null() {
442460
let _filter: Box<Regex> = mem::transmute(FILTER);
443-
FILTER = 0 as *const _;
461+
FILTER = 1 as *const _;
444462
}
445463
});
446464
}

src/libstd/io/stdio.rs

+20-24
Original file line numberDiff line numberDiff line change
@@ -25,30 +25,21 @@
2525
//! out.write(b"Hello, world!");
2626
//! ```
2727
28+
use prelude::v1::*;
2829
use self::StdSource::*;
2930

30-
use boxed::Box;
3131
use cell::RefCell;
32-
use clone::Clone;
3332
use failure::LOCAL_STDERR;
3433
use fmt;
35-
use io::{Reader, Writer, IoResult, IoError, OtherIoError, Buffer,
36-
standard_error, EndOfFile, LineBufferedWriter, BufferedReader};
37-
use marker::{Sync, Send};
34+
use io::{IoResult, IoError, OtherIoError, standard_error, EndOfFile};
35+
use io::{LineBufferedWriter, BufferedReader};
3836
use libc;
3937
use mem;
40-
use option::Option;
41-
use option::Option::{Some, None};
42-
use ops::{Deref, DerefMut, FnOnce};
43-
use result::Result::{Ok, Err};
38+
use ops::{Deref, DerefMut};
4439
use rt;
45-
use slice::SliceExt;
46-
use str::StrExt;
47-
use string::String;
40+
use sync::{Arc, Mutex, MutexGuard, StaticMutex, MUTEX_INIT};
4841
use sys::{fs, tty};
49-
use sync::{Arc, Mutex, MutexGuard, Once, ONCE_INIT};
5042
use uint;
51-
use vec::Vec;
5243

5344
// And so begins the tale of acquiring a uv handle to a stdio stream on all
5445
// platforms in all situations. Our story begins by splitting the world into two
@@ -217,14 +208,15 @@ impl Reader for StdinReader {
217208
pub fn stdin() -> StdinReader {
218209
// We're following the same strategy as kimundi's lazy_static library
219210
static mut STDIN: *const StdinReader = 0 as *const StdinReader;
220-
static ONCE: Once = ONCE_INIT;
211+
static LOCK: StaticMutex = MUTEX_INIT;
221212

222213
unsafe {
223-
ONCE.call_once(|| {
224-
// The default buffer capacity is 64k, but apparently windows doesn't like
225-
// 64k reads on stdin. See #13304 for details, but the idea is that on
226-
// windows we use a slightly smaller buffer that's been seen to be
227-
// acceptable.
214+
let _g = LOCK.lock();
215+
if STDIN as uint == 0 {
216+
// The default buffer capacity is 64k, but apparently windows
217+
// doesn't like 64k reads on stdin. See #13304 for details, but the
218+
// idea is that on windows we use a slightly smaller buffer that's
219+
// been seen to be acceptable.
228220
let stdin = if cfg!(windows) {
229221
BufferedReader::with_capacity(8 * 1024, stdin_raw())
230222
} else {
@@ -237,11 +229,15 @@ pub fn stdin() -> StdinReader {
237229

238230
// Make sure to free it at exit
239231
rt::at_exit(|| {
240-
mem::transmute::<_, Box<StdinReader>>(STDIN);
241-
STDIN = 0 as *const _;
232+
let g = LOCK.lock();
233+
let stdin = STDIN;
234+
STDIN = 1 as *const _;
235+
drop(g);
236+
mem::transmute::<_, Box<StdinReader>>(stdin);
242237
});
243-
});
244-
238+
} else if STDIN as uint == 1 {
239+
panic!("accessing stdin after the main thread has exited")
240+
}
245241
(*STDIN).clone()
246242
}
247243
}

src/libstd/lib.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -251,13 +251,14 @@ pub mod collections;
251251
pub mod thread;
252252
pub mod sync;
253253

254+
#[macro_use]
255+
#[path = "sys/common/mod.rs"] mod sys_common;
256+
254257
#[cfg(unix)]
255258
#[path = "sys/unix/mod.rs"] mod sys;
256259
#[cfg(windows)]
257260
#[path = "sys/windows/mod.rs"] mod sys;
258261

259-
#[path = "sys/common/mod.rs"] mod sys_common;
260-
261262
pub mod rt;
262263
mod failure;
263264

src/libstd/rt/at_exit_imp.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ type Queue = Vec<Thunk>;
2929
static LOCK: Mutex = MUTEX_INIT;
3030
static mut QUEUE: *mut Queue = 0 as *mut Queue;
3131

32+
const DTOR_RUN_ITERS: uint = 10;
33+
3234
unsafe fn init() {
3335
if QUEUE.is_null() {
3436
let state: Box<Queue> = box Vec::new();
@@ -49,7 +51,7 @@ pub fn cleanup() {
4951
unsafe {
5052
LOCK.lock();
5153
let queue = QUEUE;
52-
QUEUE = 1 as *mut _;
54+
QUEUE = 1u as *mut _;
5355
LOCK.unlock();
5456

5557
// make sure we're not recursively cleaning up

src/libstd/rt/mod.rs

+7-18
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,7 @@ fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int {
9494
// but we just do this to name the main thread and to give it correct
9595
// info about the stack bounds.
9696
let thread: Thread = NewThread::new(Some("<main>".to_string()));
97-
thread_info::set((my_stack_bottom, my_stack_top),
98-
sys::thread::guard::main(),
99-
thread);
97+
thread_info::set(sys::thread::guard::main(), thread);
10098

10199
// By default, some platforms will send a *signal* when a EPIPE error
102100
// would otherwise be delivered. This runtime doesn't install a SIGPIPE
@@ -135,20 +133,14 @@ fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int {
135133
}
136134
}
137135

138-
/// Enqueues a procedure to run when the runtime is cleaned up
139-
///
140-
/// The procedure passed to this function will be executed as part of the
141-
/// runtime cleanup phase. For normal rust programs, this means that it will run
142-
/// after all other threads have exited.
143-
///
144-
/// The procedure is *not* executed with a local `Thread` available to it, so
145-
/// primitives like logging, I/O, channels, spawning, etc, are *not* available.
146-
/// This is meant for "bare bones" usage to clean up runtime details, this is
147-
/// not meant as a general-purpose "let's clean everything up" function.
136+
/// Enqueues a procedure to run when the main thread exits.
148137
///
149138
/// It is forbidden for procedures to register more `at_exit` handlers when they
150139
/// are running, and doing so will lead to a process abort.
151-
pub fn at_exit<F:FnOnce()+Send>(f: F) {
140+
///
141+
/// Note that other threads may still be running when `at_exit` routines start
142+
/// running.
143+
pub fn at_exit<F: FnOnce() + Send>(f: F) {
152144
at_exit_imp::push(Thunk::new(f));
153145
}
154146

@@ -164,8 +156,5 @@ pub fn at_exit<F:FnOnce()+Send>(f: F) {
164156
pub unsafe fn cleanup() {
165157
args::cleanup();
166158
sys::stack_overflow::cleanup();
167-
// FIXME: (#20012): the resources being cleaned up by at_exit
168-
// currently are not prepared for cleanup to happen asynchronously
169-
// with detached threads using the resources; for now, we leak.
170-
// at_exit_imp::cleanup();
159+
at_exit_imp::cleanup();
171160
}

src/libstd/rt/unwind.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ use intrinsics;
6868
use libc::c_void;
6969
use mem;
7070
use sync::atomic::{self, Ordering};
71-
use sync::{Once, ONCE_INIT};
71+
use sys_common::mutex::{Mutex, MUTEX_INIT};
7272

7373
use rt::libunwind as uw;
7474

@@ -529,11 +529,20 @@ pub fn begin_unwind<M: Any + Send>(msg: M, file_line: &(&'static str, uint)) ->
529529
/// Doing this split took the LLVM IR line counts of `fn main() { panic!()
530530
/// }` from ~1900/3700 (-O/no opts) to 180/590.
531531
#[inline(never)] #[cold] // this is the slow path, please never inline this
532-
fn begin_unwind_inner(msg: Box<Any + Send>, file_line: &(&'static str, uint)) -> ! {
532+
fn begin_unwind_inner(msg: Box<Any + Send>,
533+
file_line: &(&'static str, uint)) -> ! {
533534
// Make sure the default failure handler is registered before we look at the
534535
// callbacks.
535-
static INIT: Once = ONCE_INIT;
536-
INIT.call_once(|| unsafe { register(failure::on_fail); });
536+
unsafe {
537+
static LOCK: Mutex = MUTEX_INIT;
538+
static mut INIT: bool = false;
539+
LOCK.lock();
540+
if !INIT {
541+
register(failure::on_fail);
542+
INIT = true;
543+
}
544+
LOCK.unlock();
545+
}
537546

538547
// First, invoke call the user-defined callbacks triggered on thread panic.
539548
//

src/libstd/sys/common/helper_thread.rs

+24-5
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,17 @@ struct RaceBox(helper_signal::signal);
6969
unsafe impl Send for RaceBox {}
7070
unsafe impl Sync for RaceBox {}
7171

72+
macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => (
73+
static $name: Helper<$m> = Helper {
74+
lock: ::sync::MUTEX_INIT,
75+
cond: ::sync::CONDVAR_INIT,
76+
chan: ::cell::UnsafeCell { value: 0 as *mut Sender<$m> },
77+
signal: ::cell::UnsafeCell { value: 0 },
78+
initialized: ::cell::UnsafeCell { value: false },
79+
shutdown: ::cell::UnsafeCell { value: false },
80+
};
81+
) }
82+
7283
impl<M: Send> Helper<M> {
7384
/// Lazily boots a helper thread, becoming a no-op if the helper has already
7485
/// been spawned.
@@ -85,7 +96,7 @@ impl<M: Send> Helper<M> {
8596
{
8697
unsafe {
8798
let _guard = self.lock.lock().unwrap();
88-
if !*self.initialized.get() {
99+
if *self.chan.get() as uint == 0 {
89100
let (tx, rx) = channel();
90101
*self.chan.get() = mem::transmute(box tx);
91102
let (receive, send) = helper_signal::new();
@@ -94,15 +105,17 @@ impl<M: Send> Helper<M> {
94105
let receive = RaceBox(receive);
95106

96107
let t = f();
97-
Thread::spawn(move |:| {
108+
Thread::spawn(move || {
98109
helper(receive.0, rx, t);
99110
let _g = self.lock.lock().unwrap();
100111
*self.shutdown.get() = true;
101112
self.cond.notify_one()
102113
});
103114

104-
rt::at_exit(move|:| { self.shutdown() });
115+
rt::at_exit(move || { self.shutdown() });
105116
*self.initialized.get() = true;
117+
} else if *self.chan.get() as uint == 1 {
118+
panic!("cannot continue usage after shutdown");
106119
}
107120
}
108121
}
@@ -117,7 +130,9 @@ impl<M: Send> Helper<M> {
117130
// Must send and *then* signal to ensure that the child receives the
118131
// message. Otherwise it could wake up and go to sleep before we
119132
// send the message.
120-
assert!(!self.chan.get().is_null());
133+
assert!(*self.chan.get() as uint != 0);
134+
assert!(*self.chan.get() as uint != 1,
135+
"cannot continue usage after shutdown");
121136
(**self.chan.get()).send(msg).unwrap();
122137
helper_signal::signal(*self.signal.get() as helper_signal::signal);
123138
}
@@ -130,9 +145,13 @@ impl<M: Send> Helper<M> {
130145
// returns.
131146
let mut guard = self.lock.lock().unwrap();
132147

148+
let ptr = *self.chan.get();
149+
if ptr as uint == 1 {
150+
panic!("cannot continue usage after shutdown");
151+
}
133152
// Close the channel by destroying it
134153
let chan: Box<Sender<M>> = mem::transmute(*self.chan.get());
135-
*self.chan.get() = 0 as *mut Sender<M>;
154+
*self.chan.get() = 1 as *mut Sender<M>;
136155
drop(chan);
137156
helper_signal::signal(*self.signal.get() as helper_signal::signal);
138157

src/libstd/sys/common/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
// except according to those terms.
1010

1111
#![allow(missing_docs)]
12-
#![allow(dead_code)]
1312

1413
use io::{self, IoError, IoResult};
1514
use prelude::v1::*;
@@ -19,9 +18,10 @@ use num::Int;
1918
use path::BytesContainer;
2019
use collections;
2120

21+
#[macro_use] pub mod helper_thread;
22+
2223
pub mod backtrace;
2324
pub mod condvar;
24-
pub mod helper_thread;
2525
pub mod mutex;
2626
pub mod net;
2727
pub mod rwlock;

src/libstd/sys/common/mutex.rs

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ impl Mutex {
2929
/// Behavior is undefined if the mutex is moved after the first method is
3030
/// called on the mutex.
3131
#[inline]
32+
#[allow(dead_code)] // sys is not exported yet
3233
pub unsafe fn new() -> Mutex { Mutex(imp::Mutex::new()) }
3334

3435
/// Lock the mutex blocking the current thread until it is available.

src/libstd/sys/common/net.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ use str;
2525
use sys::{self, retry, c, sock_t, last_error, last_net_error, last_gai_error, close_sock,
2626
wrlen, msglen_t, os, wouldblock, set_nonblocking, timer, ms_to_timeval,
2727
decode_error_detailed};
28-
use sync::{Arc, Mutex, MutexGuard};
28+
use sync::{Arc, Mutex};
29+
#[cfg(not(target_os = "linux"))]
30+
use sync::MutexGuard;
2931
use sys_common::{self, keep_going, short_write, timeout};
3032
use cmp;
3133
use io;
@@ -613,11 +615,13 @@ impl Drop for Inner {
613615
fn drop(&mut self) { unsafe { close_sock(self.fd); } }
614616
}
615617

618+
#[cfg(not(target_os = "linux"))]
616619
pub struct Guard<'a> {
617620
pub fd: sock_t,
618621
pub guard: MutexGuard<'a, ()>,
619622
}
620623

624+
#[cfg(not(target_os = "linux"))]
621625
#[unsafe_destructor]
622626
impl<'a> Drop for Guard<'a> {
623627
fn drop(&mut self) {

0 commit comments

Comments
 (0)