-
-
Notifications
You must be signed in to change notification settings - Fork 14.3k
Description
Unlike normal static variables (or the differently implemented unstable #[thread_local] statics), thread_local!/LocalKey statics are still dropped after calling std::process::exit().
I tried this code:
#![feature(thread_local)]
use std::sync::LazyLock;
#[derive(Debug)]
struct Droppable {
name: &'static str
}
impl Drop for Droppable {
fn drop(&mut self) {
println!("Dropping {}", self.name);
println!("{}", std::backtrace::Backtrace::force_capture());
}
}
impl Droppable {
fn new(name: &'static str) -> Self {
return Self {
name
};
}
}
static SHARED_STATIC: LazyLock<Droppable> = LazyLock::new(|| Droppable::new("SHARED_STATIC"));
thread_local! {
static TLS_STATIC: Droppable = Droppable::new("TLS_STATIC");
}
#[thread_local]
static UNSTABLE_THREAD_LOCAL: LazyLock<Droppable> = LazyLock::new(|| Droppable::new("UNSTABLE_THREAD_LOCAL"));
fn main() {
// Force initialize
LazyLock::force(&SHARED_STATIC);
LazyLock::force(&UNSTABLE_THREAD_LOCAL);
TLS_STATIC.with(|_| {});
println!("std::process::exit(1)");
std::process::exit(1);
}I expected to see this happen: No output from drop() since the documentation for std::process::exit() makes a point of saying no destructors will be called and the program will exit immediately. When calling exit, I assumed that almost nothing happens after that.
Instead, this happened: The static variable wrapped with thread_local! had its drop implementation called after calling std::process::exit() meanwhile a normal static variable and one with the unstable #[thread_local] attribute did not.
Other notes: The same behavior occurs where only the thread_local! value is dropped when normally exiting from main().
LocalKey's documentation sort of makes it sound like this is intentional behavior that the destructors are run even when exiting the main thread (See "Platform-specific behavior" 1.). If this is working as intended, it would be nice if the documentation were slightly clearer.
Meta
rustc --version --verbose:
rustc 1.81.0-nightly (20ae37c18 2024-07-07)
binary: rustc
commit-hash: 20ae37c18df95f9246c019b04957d23b4164bf7a
commit-date: 2024-07-07
host: x86_64-unknown-linux-gnu
release: 1.81.0-nightly
LLVM version: 18.1.7
Backtrace
0: <playground::Droppable as core::ops::drop::Drop>::drop
at ./src/main.rs:12:24
1: core::ptr::drop_in_place<playground::Droppable>
at /rustc/5315cbe15b79533f380bbb6685aa5480d5ff4ef5/library/core/src/ptr/mod.rs:542:1
2: core::ptr::drop_in_place<std::sys::thread_local::native::lazy::State<playground::Droppable,()>>
at /rustc/5315cbe15b79533f380bbb6685aa5480d5ff4ef5/library/core/src/ptr/mod.rs:542:1
3: core::mem::drop
at /rustc/5315cbe15b79533f380bbb6685aa5480d5ff4ef5/library/core/src/mem/mod.rs:938:24
4: std::sys::thread_local::native::lazy::destroy::{{closure}}
at /rustc/5315cbe15b79533f380bbb6685aa5480d5ff4ef5/library/std/src/sys/thread_local/native/lazy.rs:99:9
5: std::sys::thread_local::abort_on_dtor_unwind
at /rustc/5315cbe15b79533f380bbb6685aa5480d5ff4ef5/library/std/src/sys/thread_local/mod.rs:168:5
6: std::sys::thread_local::native::lazy::destroy
at /rustc/5315cbe15b79533f380bbb6685aa5480d5ff4ef5/library/std/src/sys/thread_local/native/lazy.rs:94:5
7: __call_tls_dtors
8: <unknown>
9: exit
10: std::sys::pal::unix::os::exit
at /rustc/5315cbe15b79533f380bbb6685aa5480d5ff4ef5/library/std/src/sys/pal/unix/os.rs:761:14
11: std::process::exit
at /rustc/5315cbe15b79533f380bbb6685aa5480d5ff4ef5/library/std/src/process.rs:2320:5
12: playground::main
at ./src/main.rs:40:5
13: core::ops::function::FnOnce::call_once
at /rustc/5315cbe15b79533f380bbb6685aa5480d5ff4ef5/library/core/src/ops/function.rs:250:5
14: std::sys::backtrace::__rust_begin_short_backtrace
at /rustc/5315cbe15b79533f380bbb6685aa5480d5ff4ef5/library/std/src/sys/backtrace.rs:155:18
15: std::rt::lang_start::{{closure}}
at /rustc/5315cbe15b79533f380bbb6685aa5480d5ff4ef5/library/std/src/rt.rs:159:18
16: core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once
at /rustc/5315cbe15b79533f380bbb6685aa5480d5ff4ef5/library/core/src/ops/function.rs:284:13
17: std::panicking::try::do_call
at /rustc/5315cbe15b79533f380bbb6685aa5480d5ff4ef5/library/std/src/panicking.rs:553:40
18: std::panicking::try
at /rustc/5315cbe15b79533f380bbb6685aa5480d5ff4ef5/library/std/src/panicking.rs:517:19
19: std::panic::catch_unwind
at /rustc/5315cbe15b79533f380bbb6685aa5480d5ff4ef5/library/std/src/panic.rs:350:14
20: std::rt::lang_start_internal::{{closure}}
at /rustc/5315cbe15b79533f380bbb6685aa5480d5ff4ef5/library/std/src/rt.rs:141:48
21: std::panicking::try::do_call
at /rustc/5315cbe15b79533f380bbb6685aa5480d5ff4ef5/library/std/src/panicking.rs:553:40
22: std::panicking::try
at /rustc/5315cbe15b79533f380bbb6685aa5480d5ff4ef5/library/std/src/panicking.rs:517:19
23: std::panic::catch_unwind
at /rustc/5315cbe15b79533f380bbb6685aa5480d5ff4ef5/library/std/src/panic.rs:350:14
24: std::rt::lang_start_internal
at /rustc/5315cbe15b79533f380bbb6685aa5480d5ff4ef5/library/std/src/rt.rs:141:20
25: std::rt::lang_start
at /rustc/5315cbe15b79533f380bbb6685aa5480d5ff4ef5/library/std/src/rt.rs:158:17
26: main
27: __libc_start_main
28: _start