Skip to content

Commit 68d6941

Browse files
committed
Auto merge of #23267 - alexcrichton:issue-20012, r=aturon
This reverts commit aec67c2. Closes #20012 This is temporarily rebased on #23245 as it would otherwise conflict, the last commit is the only one relevant to this PR though.
2 parents 3900c08 + 1cc9718 commit 68d6941

File tree

10 files changed

+86
-51
lines changed

10 files changed

+86
-51
lines changed

src/liblog/lib.rs

+28-12
Original file line numberDiff line numberDiff line change
@@ -183,10 +183,9 @@ use std::io::{self, Stderr};
183183
use std::io::prelude::*;
184184
use std::mem;
185185
use std::env;
186-
use std::ptr;
187186
use std::rt;
188187
use std::slice;
189-
use std::sync::{Once, ONCE_INIT};
188+
use std::sync::{Once, ONCE_INIT, StaticMutex, MUTEX_INIT};
190189

191190
use directive::LOG_LEVEL_NAMES;
192191

@@ -202,6 +201,8 @@ pub const MAX_LOG_LEVEL: u32 = 255;
202201
/// The default logging level of a crate if no other is specified.
203202
const DEFAULT_LOG_LEVEL: u32 = 1;
204203

204+
static LOCK: StaticMutex = MUTEX_INIT;
205+
205206
/// An unsafe constant that is the maximum logging level of any module
206207
/// specified. This is the first line of defense to determining whether a
207208
/// logging statement should be run.
@@ -286,9 +287,18 @@ impl Drop for DefaultLogger {
286287
pub fn log(level: u32, loc: &'static LogLocation, args: fmt::Arguments) {
287288
// Test the literal string from args against the current filter, if there
288289
// is one.
289-
match unsafe { FILTER.as_ref() } {
290-
Some(filter) if !args.to_string().contains(&filter[..]) => return,
291-
_ => {}
290+
unsafe {
291+
let _g = LOCK.lock();
292+
match FILTER as uint {
293+
0 => {}
294+
1 => panic!("cannot log after main thread has exited"),
295+
n => {
296+
let filter = mem::transmute::<_, &String>(n);
297+
if !args.to_string().contains(&filter[..]) {
298+
return
299+
}
300+
}
301+
}
292302
}
293303

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

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

375-
enabled(level, module, unsafe { (*DIRECTIVES).iter() })
384+
let _g = LOCK.lock();
385+
unsafe {
386+
assert!(DIRECTIVES as uint != 0);
387+
assert!(DIRECTIVES as uint != 1,
388+
"cannot log after the main thread has exited");
389+
390+
enabled(level, module, (*DIRECTIVES).iter())
391+
}
376392
}
377393

378394
fn enabled(level: u32,
@@ -428,14 +444,14 @@ fn init() {
428444

429445
// Schedule the cleanup for the globals for when the runtime exits.
430446
rt::at_exit(move || {
447+
let _g = LOCK.lock();
431448
assert!(!DIRECTIVES.is_null());
432-
let _directives: Box<Vec<directive::LogDirective>> =
433-
Box::from_raw(DIRECTIVES);
434-
DIRECTIVES = ptr::null_mut();
449+
let _directives = Box::from_raw(DIRECTIVES);
450+
DIRECTIVES = 1 as *mut _;
435451

436452
if !FILTER.is_null() {
437-
let _filter: Box<String> = Box::from_raw(FILTER);
438-
FILTER = 0 as *mut _;
453+
let _filter = Box::from_raw(FILTER);
454+
FILTER = 1 as *mut _;
439455
}
440456
});
441457
}

src/libstd/rt/mod.rs

+6-15
Original file line numberDiff line numberDiff line change
@@ -147,20 +147,14 @@ fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int {
147147
}
148148
}
149149

150-
/// Enqueues a procedure to run when the runtime is cleaned up
151-
///
152-
/// The procedure passed to this function will be executed as part of the
153-
/// runtime cleanup phase. For normal rust programs, this means that it will run
154-
/// after all other threads have exited.
155-
///
156-
/// The procedure is *not* executed with a local `Thread` available to it, so
157-
/// primitives like logging, I/O, channels, spawning, etc, are *not* available.
158-
/// This is meant for "bare bones" usage to clean up runtime details, this is
159-
/// not meant as a general-purpose "let's clean everything up" function.
150+
/// Enqueues a procedure to run when the main thread exits.
160151
///
161152
/// It is forbidden for procedures to register more `at_exit` handlers when they
162153
/// are running, and doing so will lead to a process abort.
163-
pub fn at_exit<F:FnOnce()+Send+'static>(f: F) {
154+
///
155+
/// Note that other threads may still be running when `at_exit` routines start
156+
/// running.
157+
pub fn at_exit<F: FnOnce() + Send + 'static>(f: F) {
164158
at_exit_imp::push(Thunk::new(f));
165159
}
166160

@@ -176,8 +170,5 @@ pub fn at_exit<F:FnOnce()+Send+'static>(f: F) {
176170
pub unsafe fn cleanup() {
177171
args::cleanup();
178172
sys::stack_overflow::cleanup();
179-
// FIXME: (#20012): the resources being cleaned up by at_exit
180-
// currently are not prepared for cleanup to happen asynchronously
181-
// with detached threads using the resources; for now, we leak.
182-
// at_exit_imp::cleanup();
173+
at_exit_imp::cleanup();
183174
}

src/libstd/rt/unwind.rs

+17-6
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ use intrinsics;
6969
use libc::c_void;
7070
use mem;
7171
use sync::atomic::{self, Ordering};
72-
use sync::{Once, ONCE_INIT};
72+
use sys_common::mutex::{Mutex, MUTEX_INIT};
7373

7474
use rt::libunwind as uw;
7575

@@ -534,11 +534,22 @@ pub fn begin_unwind<M: Any + Send>(msg: M, file_line: &(&'static str, uint)) ->
534534
/// Doing this split took the LLVM IR line counts of `fn main() { panic!()
535535
/// }` from ~1900/3700 (-O/no opts) to 180/590.
536536
#[inline(never)] #[cold] // this is the slow path, please never inline this
537-
fn begin_unwind_inner(msg: Box<Any + Send>, file_line: &(&'static str, uint)) -> ! {
538-
// Make sure the default panic handler is registered before we look at the
539-
// callbacks.
540-
static INIT: Once = ONCE_INIT;
541-
INIT.call_once(|| unsafe { register(panicking::on_panic); });
537+
fn begin_unwind_inner(msg: Box<Any + Send>,
538+
file_line: &(&'static str, uint)) -> ! {
539+
// Make sure the default failure handler is registered before we look at the
540+
// callbacks. We also use a raw sys-based mutex here instead of a
541+
// `std::sync` one as accessing TLS can cause weird recursive problems (and
542+
// we don't need poison checking).
543+
unsafe {
544+
static LOCK: Mutex = MUTEX_INIT;
545+
static mut INIT: bool = false;
546+
LOCK.lock();
547+
if !INIT {
548+
register(panicking::on_panic);
549+
INIT = true;
550+
}
551+
LOCK.unlock();
552+
}
542553

543554
// First, invoke call the user-defined callbacks triggered on thread panic.
544555
//

src/libstd/sys/common/helper_thread.rs

+13-6
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ use prelude::v1::*;
2424

2525
use boxed;
2626
use cell::UnsafeCell;
27-
use ptr;
2827
use rt;
2928
use sync::{StaticMutex, StaticCondvar};
3029
use sync::mpsc::{channel, Sender, Receiver};
@@ -97,7 +96,7 @@ impl<M: Send> Helper<M> {
9796
{
9897
unsafe {
9998
let _guard = self.lock.lock().unwrap();
100-
if !*self.initialized.get() {
99+
if *self.chan.get() as uint == 0 {
101100
let (tx, rx) = channel();
102101
*self.chan.get() = boxed::into_raw(box tx);
103102
let (receive, send) = helper_signal::new();
@@ -113,8 +112,10 @@ impl<M: Send> Helper<M> {
113112
self.cond.notify_one()
114113
});
115114

116-
rt::at_exit(move|| { self.shutdown() });
115+
rt::at_exit(move || { self.shutdown() });
117116
*self.initialized.get() = true;
117+
} else if *self.chan.get() as uint == 1 {
118+
panic!("cannot continue usage after shutdown");
118119
}
119120
}
120121
}
@@ -129,7 +130,9 @@ impl<M: Send> Helper<M> {
129130
// Must send and *then* signal to ensure that the child receives the
130131
// message. Otherwise it could wake up and go to sleep before we
131132
// send the message.
132-
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");
133136
(**self.chan.get()).send(msg).unwrap();
134137
helper_signal::signal(*self.signal.get() as helper_signal::signal);
135138
}
@@ -142,9 +145,13 @@ impl<M: Send> Helper<M> {
142145
// returns.
143146
let mut guard = self.lock.lock().unwrap();
144147

148+
let ptr = *self.chan.get();
149+
if ptr as uint == 1 {
150+
panic!("cannot continue usage after shutdown");
151+
}
145152
// Close the channel by destroying it
146-
let chan: Box<Sender<M>> = Box::from_raw(*self.chan.get());
147-
*self.chan.get() = ptr::null_mut();
153+
let chan = Box::from_raw(*self.chan.get());
154+
*self.chan.get() = 1 as *mut Sender<M>;
148155
drop(chan);
149156
helper_signal::signal(*self.signal.get() as helper_signal::signal);
150157

src/libstd/sys/common/thread_local.rs

-4
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@
6161
use prelude::v1::*;
6262

6363
use sync::atomic::{self, AtomicUsize, Ordering};
64-
use sync::{Mutex, Once, ONCE_INIT};
6564

6665
use sys::thread_local as imp;
6766

@@ -142,9 +141,6 @@ pub const INIT_INNER: StaticKeyInner = StaticKeyInner {
142141
key: atomic::ATOMIC_USIZE_INIT,
143142
};
144143

145-
static INIT_KEYS: Once = ONCE_INIT;
146-
static mut KEYS: *mut Mutex<Vec<imp::Key>> = 0 as *mut _;
147-
148144
impl StaticKey {
149145
/// Gets the value associated with this TLS key
150146
///

src/libstd/sys/unix/timer.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,15 @@ fn helper(input: libc::c_int, messages: Receiver<Req>, _: ()) {
170170
1 => {
171171
loop {
172172
match messages.try_recv() {
173+
// Once we've been disconnected it means the main thread
174+
// is exiting (at_exit has run). We could still have
175+
// active timers for other threads, so we're just going
176+
// to drop them all on the floor. This is all we can
177+
// really do, however, to prevent resource leakage. The
178+
// remaining timers will likely start panicking quickly
179+
// as they attempt to re-use this thread but are
180+
// disallowed to do so.
173181
Err(TryRecvError::Disconnected) => {
174-
assert!(active.len() == 0);
175182
break 'outer;
176183
}
177184

src/libstd/sys/windows/thread_local.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -138,23 +138,29 @@ unsafe fn init_dtors() {
138138
rt::at_exit(move|| {
139139
DTOR_LOCK.lock();
140140
let dtors = DTORS;
141-
DTORS = ptr::null_mut();
141+
DTORS = 1 as *mut _;
142142
Box::from_raw(dtors);
143-
assert!(DTORS.is_null()); // can't re-init after destructing
143+
assert!(DTORS as uint == 1); // can't re-init after destructing
144144
DTOR_LOCK.unlock();
145145
});
146146
}
147147

148148
unsafe fn register_dtor(key: Key, dtor: Dtor) {
149149
DTOR_LOCK.lock();
150150
init_dtors();
151+
assert!(DTORS as uint != 0);
152+
assert!(DTORS as uint != 1,
153+
"cannot create new TLS keys after the main thread has exited");
151154
(*DTORS).push((key, dtor));
152155
DTOR_LOCK.unlock();
153156
}
154157

155158
unsafe fn unregister_dtor(key: Key) -> bool {
156159
DTOR_LOCK.lock();
157160
init_dtors();
161+
assert!(DTORS as uint != 0);
162+
assert!(DTORS as uint != 1,
163+
"cannot unregister destructors after the main thread has exited");
158164
let ret = {
159165
let dtors = &mut *DTORS;
160166
let before = dtors.len();
@@ -241,7 +247,7 @@ unsafe fn run_dtors() {
241247
any_run = false;
242248
let dtors = {
243249
DTOR_LOCK.lock();
244-
let ret = if DTORS.is_null() {
250+
let ret = if DTORS as usize <= 1 {
245251
Vec::new()
246252
} else {
247253
(*DTORS).iter().map(|s| *s).collect()

src/libstd/sys/windows/timer.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,10 @@ fn helper(input: libc::HANDLE, messages: Receiver<Req>, _: ()) {
8080
None => {}
8181
}
8282
}
83+
// See the comment in unix::timer for why we don't have any
84+
// asserts here and why we're likely just leaving timers on
85+
// the floor as we exit.
8386
Err(TryRecvError::Disconnected) => {
84-
assert_eq!(objs.len(), 1);
85-
assert_eq!(chans.len(), 0);
8687
break 'outer;
8788
}
8889
Err(..) => break

src/test/run-fail/rt-set-exit-status-panic2.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ fn r(x:int) -> r {
3535

3636
fn main() {
3737
error!("whatever");
38-
let _t = thread::spawn(move|| {
38+
let _t = thread::scoped(move|| {
3939
let _i = r(5);
4040
});
4141
panic!();

src/test/run-pass/unique-send-2.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub fn main() {
2525
let _t = (0..n).map(|i| {
2626
expected += i;
2727
let tx = tx.clone();
28-
thread::spawn(move|| {
28+
thread::scoped(move|| {
2929
child(&tx, i)
3030
})
3131
}).collect::<Vec<_>>();

0 commit comments

Comments
 (0)