Skip to content

Commit ec8d61d

Browse files
committed
Rollup merge of rust-lang#23267 - alexcrichton:issue-20012, r=brson
This reverts commit aec67c2. Closes rust-lang#20012 This is temporarily rebased on rust-lang#23245 as it would otherwise conflict, the last commit is the only one relevant to this PR though.
2 parents f58a653 + 2d60fcb commit ec8d61d

38 files changed

+161
-218
lines changed

src/liblog/lib.rs

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,9 @@ use std::old_io::LineBufferedWriter;
184184
use std::old_io;
185185
use std::mem;
186186
use std::env;
187-
use std::ptr;
188187
use std::rt;
189188
use std::slice;
190-
use std::sync::{Once, ONCE_INIT};
189+
use std::sync::{Once, ONCE_INIT, StaticMutex, MUTEX_INIT};
191190

192191
use directive::LOG_LEVEL_NAMES;
193192

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

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

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

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

378-
enabled(level, module, unsafe { (*DIRECTIVES).iter() })
387+
let _g = LOCK.lock();
388+
unsafe {
389+
assert!(DIRECTIVES as uint != 0);
390+
assert!(DIRECTIVES as uint != 1,
391+
"cannot log after the main thread has exited");
392+
393+
enabled(level, module, (*DIRECTIVES).iter())
394+
}
379395
}
380396

381397
fn enabled(level: u32,
@@ -431,14 +447,14 @@ fn init() {
431447

432448
// Schedule the cleanup for the globals for when the runtime exits.
433449
rt::at_exit(move || {
450+
let _g = LOCK.lock();
434451
assert!(!DIRECTIVES.is_null());
435-
let _directives: Box<Vec<directive::LogDirective>> =
436-
Box::from_raw(DIRECTIVES);
437-
DIRECTIVES = ptr::null_mut();
452+
let _directives = Box::from_raw(DIRECTIVES);
453+
DIRECTIVES = 1 as *mut _;
438454

439455
if !FILTER.is_null() {
440-
let _filter: Box<String> = Box::from_raw(FILTER);
441-
FILTER = 0 as *mut _;
456+
let _filter = Box::from_raw(FILTER);
457+
FILTER = 1 as *mut _;
442458
}
443459
});
444460
}

src/libstd/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,13 +273,14 @@ pub mod collections;
273273
pub mod thread;
274274
pub mod sync;
275275

276+
#[macro_use]
277+
#[path = "sys/common/mod.rs"] mod sys_common;
278+
276279
#[cfg(unix)]
277280
#[path = "sys/unix/mod.rs"] mod sys;
278281
#[cfg(windows)]
279282
#[path = "sys/windows/mod.rs"] mod sys;
280283

281-
#[path = "sys/common/mod.rs"] mod sys_common;
282-
283284
pub mod rt;
284285
mod panicking;
285286

src/libstd/rt/mod.rs

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,7 @@ fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int {
108108
// but we just do this to name the main thread and to give it correct
109109
// info about the stack bounds.
110110
let thread: Thread = NewThread::new(Some("<main>".to_string()));
111-
thread_info::set((my_stack_bottom, my_stack_top),
112-
sys::thread::guard::main(),
113-
thread);
111+
thread_info::set(sys::thread::guard::main(), thread);
114112

115113
// By default, some platforms will send a *signal* when a EPIPE error
116114
// would otherwise be delivered. This runtime doesn't install a SIGPIPE
@@ -149,20 +147,14 @@ fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int {
149147
}
150148
}
151149

152-
/// Enqueues a procedure to run when the runtime is cleaned up
153-
///
154-
/// The procedure passed to this function will be executed as part of the
155-
/// runtime cleanup phase. For normal rust programs, this means that it will run
156-
/// after all other threads have exited.
157-
///
158-
/// The procedure is *not* executed with a local `Thread` available to it, so
159-
/// primitives like logging, I/O, channels, spawning, etc, are *not* available.
160-
/// This is meant for "bare bones" usage to clean up runtime details, this is
161-
/// not meant as a general-purpose "let's clean everything up" function.
150+
/// Enqueues a procedure to run when the main thread exits.
162151
///
163152
/// It is forbidden for procedures to register more `at_exit` handlers when they
164153
/// are running, and doing so will lead to a process abort.
165-
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) {
166158
at_exit_imp::push(Thunk::new(f));
167159
}
168160

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

src/libstd/rt/unwind.rs

Lines changed: 17 additions & 6 deletions
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

Lines changed: 24 additions & 6 deletions
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};
@@ -70,6 +69,17 @@ struct RaceBox(helper_signal::signal);
7069
unsafe impl Send for RaceBox {}
7170
unsafe impl Sync for RaceBox {}
7271

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+
7383
impl<M: Send> Helper<M> {
7484
/// Lazily boots a helper thread, becoming a no-op if the helper has already
7585
/// been spawned.
@@ -86,7 +96,7 @@ impl<M: Send> Helper<M> {
8696
{
8797
unsafe {
8898
let _guard = self.lock.lock().unwrap();
89-
if !*self.initialized.get() {
99+
if *self.chan.get() as uint == 0 {
90100
let (tx, rx) = channel();
91101
*self.chan.get() = boxed::into_raw(box tx);
92102
let (receive, send) = helper_signal::new();
@@ -102,8 +112,10 @@ impl<M: Send> Helper<M> {
102112
self.cond.notify_one()
103113
});
104114

105-
rt::at_exit(move|| { self.shutdown() });
115+
rt::at_exit(move || { self.shutdown() });
106116
*self.initialized.get() = true;
117+
} else if *self.chan.get() as uint == 1 {
118+
panic!("cannot continue usage after shutdown");
107119
}
108120
}
109121
}
@@ -118,7 +130,9 @@ impl<M: Send> Helper<M> {
118130
// Must send and *then* signal to ensure that the child receives the
119131
// message. Otherwise it could wake up and go to sleep before we
120132
// send the message.
121-
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");
122136
(**self.chan.get()).send(msg).unwrap();
123137
helper_signal::signal(*self.signal.get() as helper_signal::signal);
124138
}
@@ -131,9 +145,13 @@ impl<M: Send> Helper<M> {
131145
// returns.
132146
let mut guard = self.lock.lock().unwrap();
133147

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

src/libstd/sys/common/mod.rs

Lines changed: 2 additions & 2 deletions
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 old_io::{self, IoError, IoResult};
1514
use prelude::v1::*;
@@ -19,9 +18,10 @@ use num::Int;
1918
use old_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 net2;

src/libstd/sys/common/net.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ use str;
2626
use sys::{self, retry, c, sock_t, last_error, last_net_error, last_gai_error, close_sock,
2727
wrlen, msglen_t, os, wouldblock, set_nonblocking, timer, ms_to_timeval,
2828
decode_error_detailed};
29-
use sync::{Arc, Mutex, MutexGuard};
29+
use sync::{Arc, Mutex};
30+
#[cfg(not(target_os = "linux"))]
31+
use sync::MutexGuard;
3032
use sys_common::{self, keep_going, short_write, timeout};
3133
use cmp;
3234
use old_io;
@@ -620,11 +622,13 @@ impl Drop for Inner {
620622
fn drop(&mut self) { unsafe { close_sock(self.fd); } }
621623
}
622624

625+
#[cfg(not(target_os = "linux"))]
623626
pub struct Guard<'a> {
624627
pub fd: sock_t,
625628
pub guard: MutexGuard<'a, ()>,
626629
}
627630

631+
#[cfg(not(target_os = "linux"))]
628632
#[unsafe_destructor]
629633
impl<'a> Drop for Guard<'a> {
630634
fn drop(&mut self) {

src/libstd/sys/common/net2.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ use io::{self, Error, ErrorKind};
1515
use libc::{self, c_int, c_char, c_void, socklen_t};
1616
use mem;
1717
use net::{IpAddr, SocketAddr, Shutdown};
18-
use num::Int;
1918
use sys::c;
2019
use sys::net::{cvt, cvt_r, cvt_gai, Socket, init, wrlen_t};
2120
use sys_common::{AsInner, FromInner, IntoInner};
@@ -24,9 +23,6 @@ use sys_common::{AsInner, FromInner, IntoInner};
2423
// sockaddr and misc bindings
2524
////////////////////////////////////////////////////////////////////////////////
2625

27-
fn hton<I: Int>(i: I) -> I { i.to_be() }
28-
fn ntoh<I: Int>(i: I) -> I { Int::from_be(i) }
29-
3026
fn setsockopt<T>(sock: &Socket, opt: c_int, val: c_int,
3127
payload: T) -> io::Result<()> {
3228
unsafe {
@@ -39,7 +35,7 @@ fn setsockopt<T>(sock: &Socket, opt: c_int, val: c_int,
3935

4036
#[allow(dead_code)]
4137
fn getsockopt<T: Copy>(sock: &Socket, opt: c_int,
42-
val: c_int) -> io::Result<T> {
38+
val: c_int) -> io::Result<T> {
4339
unsafe {
4440
let mut slot: T = mem::zeroed();
4541
let mut len = mem::size_of::<T>() as socklen_t;

src/libstd/sys/common/stack.rs

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -121,37 +121,6 @@ pub unsafe fn record_os_managed_stack_bounds(stack_lo: uint, _stack_hi: uint) {
121121
record_sp_limit(stack_lo + RED_ZONE);
122122
}
123123

124-
#[inline(always)]
125-
pub unsafe fn record_rust_managed_stack_bounds(stack_lo: uint, stack_hi: uint) {
126-
// When the old runtime had segmented stacks, it used a calculation that was
127-
// "limit + RED_ZONE + FUDGE". The red zone was for things like dynamic
128-
// symbol resolution, llvm function calls, etc. In theory this red zone
129-
// value is 0, but it matters far less when we have gigantic stacks because
130-
// we don't need to be so exact about our stack budget. The "fudge factor"
131-
// was because LLVM doesn't emit a stack check for functions < 256 bytes in
132-
// size. Again though, we have giant stacks, so we round all these
133-
// calculations up to the nice round number of 20k.
134-
record_sp_limit(stack_lo + RED_ZONE);
135-
136-
return target_record_stack_bounds(stack_lo, stack_hi);
137-
138-
#[cfg(not(windows))] #[inline(always)]
139-
unsafe fn target_record_stack_bounds(_stack_lo: uint, _stack_hi: uint) {}
140-
141-
#[cfg(all(windows, target_arch = "x86"))] #[inline(always)]
142-
unsafe fn target_record_stack_bounds(stack_lo: uint, stack_hi: uint) {
143-
// stack range is at TIB: %fs:0x04 (top) and %fs:0x08 (bottom)
144-
asm!("mov $0, %fs:0x04" :: "r"(stack_hi) :: "volatile");
145-
asm!("mov $0, %fs:0x08" :: "r"(stack_lo) :: "volatile");
146-
}
147-
#[cfg(all(windows, target_arch = "x86_64"))] #[inline(always)]
148-
unsafe fn target_record_stack_bounds(stack_lo: uint, stack_hi: uint) {
149-
// stack range is at TIB: %gs:0x08 (top) and %gs:0x10 (bottom)
150-
asm!("mov $0, %gs:0x08" :: "r"(stack_hi) :: "volatile");
151-
asm!("mov $0, %gs:0x10" :: "r"(stack_lo) :: "volatile");
152-
}
153-
}
154-
155124
/// Records the current limit of the stack as specified by `end`.
156125
///
157126
/// This is stored in an OS-dependent location, likely inside of the thread

0 commit comments

Comments
 (0)