Skip to content

Commit 95e9609

Browse files
committed
std: Flag Windows TLS dtor symbol as #[used]
Turns out ThinLTO was internalizing this symbol and eliminating it. Worse yet if you compiled with LTO turns out no TLS destructors would run on Windows! The `#[used]` annotation should be a more bulletproof implementation (in the face of LTO) of preserving this symbol all the way through in LLVM and ensuring it makes it all the way to the linker which will take care of it.
1 parent 47498de commit 95e9609

File tree

3 files changed

+44
-1
lines changed

3 files changed

+44
-1
lines changed

src/libstd/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@
332332
#![feature(doc_spotlight)]
333333
#![cfg_attr(test, feature(update_panic_count))]
334334
#![cfg_attr(windows, feature(const_atomic_ptr_new))]
335+
#![cfg_attr(windows, feature(used))]
335336

336337
#![default_lib_allocator]
337338

src/libstd/sys/windows/thread_local.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,9 @@ unsafe fn register_dtor(key: Key, dtor: Dtor) {
200200
// the address of the symbol to ensure it sticks around.
201201

202202
#[link_section = ".CRT$XLB"]
203-
#[linkage = "external"]
204203
#[allow(dead_code, unused_variables)]
204+
#[used] // we don't want LLVM eliminating this symbol for any reason, and
205+
// when the symbol makes it to the linker the linker will take over
205206
pub static p_thread_callback: unsafe extern "system" fn(c::LPVOID, c::DWORD,
206207
c::LPVOID) =
207208
on_tls_callback;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-flags: -C lto
12+
// no-prefer-dynamic
13+
// ignore-emscripten no threads support
14+
15+
use std::thread;
16+
17+
static mut HIT: usize = 0;
18+
19+
thread_local!(static A: Foo = Foo);
20+
21+
struct Foo;
22+
23+
impl Drop for Foo {
24+
fn drop(&mut self) {
25+
unsafe {
26+
HIT += 1;
27+
}
28+
}
29+
}
30+
31+
fn main() {
32+
unsafe {
33+
assert_eq!(HIT, 0);
34+
thread::spawn(|| {
35+
assert_eq!(HIT, 0);
36+
A.with(|_| ());
37+
assert_eq!(HIT, 0);
38+
}).join().unwrap();
39+
assert_eq!(HIT, 1);
40+
}
41+
}

0 commit comments

Comments
 (0)