Skip to content

Commit

Permalink
std: Flag Windows TLS dtor symbol as #[used]
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
alexcrichton committed Nov 24, 2017
1 parent 47498de commit 95e9609
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/libstd/lib.rs
Expand Up @@ -332,6 +332,7 @@
#![feature(doc_spotlight)]
#![cfg_attr(test, feature(update_panic_count))]
#![cfg_attr(windows, feature(const_atomic_ptr_new))]
#![cfg_attr(windows, feature(used))]

#![default_lib_allocator]

Expand Down
3 changes: 2 additions & 1 deletion src/libstd/sys/windows/thread_local.rs
Expand Up @@ -200,8 +200,9 @@ unsafe fn register_dtor(key: Key, dtor: Dtor) {
// the address of the symbol to ensure it sticks around.

#[link_section = ".CRT$XLB"]
#[linkage = "external"]
#[allow(dead_code, unused_variables)]
#[used] // we don't want LLVM eliminating this symbol for any reason, and
// when the symbol makes it to the linker the linker will take over
pub static p_thread_callback: unsafe extern "system" fn(c::LPVOID, c::DWORD,
c::LPVOID) =
on_tls_callback;
Expand Down
41 changes: 41 additions & 0 deletions src/test/run-pass/lto-still-runs-thread-dtors.rs
@@ -0,0 +1,41 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// compile-flags: -C lto
// no-prefer-dynamic
// ignore-emscripten no threads support

use std::thread;

static mut HIT: usize = 0;

thread_local!(static A: Foo = Foo);

struct Foo;

impl Drop for Foo {
fn drop(&mut self) {
unsafe {
HIT += 1;
}
}
}

fn main() {
unsafe {
assert_eq!(HIT, 0);
thread::spawn(|| {
assert_eq!(HIT, 0);
A.with(|_| ());
assert_eq!(HIT, 0);
}).join().unwrap();
assert_eq!(HIT, 1);
}
}

0 comments on commit 95e9609

Please sign in to comment.