Skip to content

std::thread::spawn: thread-local storage panics #138696

Closed
@yellowhatter

Description

@yellowhatter

Hello, rust-team!

Code

I tried this code:

#[test]
fn spawn_in_atexit_main() {
    unsafe { libc::atexit(spawn_in_atexit) };
}

extern "C" fn spawn_in_atexit() {
    let _ = std::thread::spawn(|| {
        println!("Thread spawned in atexit");
    });
}

I expected to see this happen: thread spawned normally

Instead, this happened: panic at std::thread::spawnhook::run_spawn_hooks because it tries to talk to TLS which is not available inside of atexit context. Earlier versions of thread didn't have this hooks functionality and were OK spawning inside atexit and we tested it on Win, Mac and Linux.
Functionality to spawn thread inside atexit is very important as it is a silver bullet workaround to execute some TLS-using code from atexit context.

Version it worked on

It most recently worked on: at least 1.75

Version with regression

rustc --version --verbose:

rustc 1.85.1 (4eb161250 2025-03-15)
binary: rustc
commit-hash: 4eb161250e340c8f48f66e2b929ef4a5bed7c181
commit-date: 2025-03-15
host: x86_64-unknown-linux-gnu
release: 1.85.1
LLVM version: 19.1.7

Backtrace

Backtrace

thread 'main' panicked at library/std/src/thread/local.rs:272:26:
cannot access a Thread Local Storage value during or after destruction: AccessError
stack backtrace:
   0: rust_begin_unwind
             at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/std/src/panicking.rs:692:5
   1: core::panicking::panic_fmt
             at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/core/src/panicking.rs:75:14
   2: core::result::unwrap_failed
             at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/core/src/result.rs:1704:5
   3: core::result::Result<T,E>::expect
             at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/core/src/result.rs:1061:23
   4: std::thread::local::LocalKey<T>::with
             at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/std/src/thread/local.rs:272:9
   5: std::thread::spawnhook::run_spawn_hooks
             at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/std/src/thread/spawnhook.rs:116:29
   6: std::thread::Builder::spawn_unchecked_
             at /home/hatter/.rustup/toolchains/1.85.0-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/mod.rs:512:13
   7: std::thread::Builder::spawn_unchecked
             at /home/hatter/.rustup/toolchains/1.85.0-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/mod.rs:469:32
   8: std::thread::Builder::spawn
             at /home/hatter/.rustup/toolchains/1.85.0-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/mod.rs:401:18
   9: std::thread::spawn
             at /home/hatter/.rustup/toolchains/1.85.0-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/mod.rs:734:20
  10: atexit::spawn_in_atexit
             at ./tests/atexit.rs:88:13
  11: __run_exit_handlers
             at ./stdlib/exit.c:108:8
  12: __GI_exit
             at ./stdlib/exit.c:138:3
  13: __libc_start_call_main
             at ./csu/../sysdeps/nptl/libc_start_call_main.h:74:3
  14: __libc_start_main_impl
             at ./csu/../csu/libc-start.c:360:3
  15: _start
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

thread 'main' panicked at library/core/src/panicking.rs:218:5:
panic in a function that cannot unwind
stack backtrace:
   0:     0x65482003492a - std::backtrace_rs::backtrace::libunwind::trace::h88deb10bd0145eb8
                               at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/std/src/../../backtrace/src/backtrace/libunwind.rs:116:5
   1:     0x65482003492a - std::backtrace_rs::backtrace::trace_unsynchronized::he1036f5481c14dff
                               at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
   2:     0x65482003492a - std::sys::backtrace::_print_fmt::hecc345b6e70c4b20
                               at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/std/src/sys/backtrace.rs:66:9
   3:     0x65482003492a - <std::sys::backtrace::BacktraceLock::print::DisplayBacktrace as core::fmt::Display>::fmt::he089f96442833f67
                               at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/std/src/sys/backtrace.rs:39:26
   4:     0x654820060683 - core::fmt::rt::Argument::fmt::h1f77cded99c71a14
                               at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/core/src/fmt/rt.rs:177:76
   5:     0x654820060683 - core::fmt::write::h2f210ed4c94745cb
                               at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/core/src/fmt/mod.rs:1440:21
   6:     0x654820030423 - std::io::Write::write_fmt::h7de08171ab770fb2
                               at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/std/src/io/mod.rs:1887:15
   7:     0x654820034772 - std::sys::backtrace::BacktraceLock::print::h810fbd31421329e6
                               at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/std/src/sys/backtrace.rs:42:9
   8:     0x654820035e60 - std::panicking::default_hook::{{closure}}::hbaad47ed9dc6356d
                               at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/std/src/panicking.rs:295:22
   9:     0x654820035c40 - std::panicking::default_hook::h24e207139139d40a
                               at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/std/src/panicking.rs:322:9
  10:     0x6548200365c2 - std::panicking::rust_panic_with_hook::ha9131beeb2ddc506
                               at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/std/src/panicking.rs:828:13
  11:     0x654820036336 - std::panicking::begin_panic_handler::{{closure}}::h1bba0eaeb6da506f
                               at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/std/src/panicking.rs:694:13
  12:     0x654820034e29 - std::sys::backtrace::__rust_end_short_backtrace::h1d1ca3eade483f4c
                               at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/std/src/sys/backtrace.rs:168:18
  13:     0x654820035ffd - rust_begin_unwind
                               at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/std/src/panicking.rs:692:5
  14:     0x65481ebd45ed - core::panicking::panic_nounwind_fmt::runtime::hdd2d1a56a8b6cee7
                               at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/core/src/panicking.rs:117:22
  15:     0x65481ebd45ed - core::panicking::panic_nounwind_fmt::h0d5ff668f956fac4
                               at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/core/src/intrinsics/mod.rs:3869:9
  16:     0x65481ebd4682 - core::panicking::panic_nounwind::h385b7d9bda51382d
                               at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/core/src/panicking.rs:218:5
  17:     0x65481ebd4846 - core::panicking::panic_cannot_unwind::h757b6ea37bf9b60a
                               at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/core/src/panicking.rs:307:5
  18:     0x65481ec436e9 - atexit::spawn_in_atexit::h8fbdd131c26eac2f
                               at /home/hatter/work/repos/zenoh/zenoh/tests/atexit.rs:87:1
  19:     0x7982d2a47a76 - __run_exit_handlers
                               at ./stdlib/exit.c:108:8
  20:     0x7982d2a47bbe - __GI_exit
                               at ./stdlib/exit.c:138:3
  21:     0x7982d2a2a1d1 - __libc_start_call_main
                               at ./csu/../sysdeps/nptl/libc_start_call_main.h:74:3
  22:     0x7982d2a2a28b - __libc_start_main_impl
                               at ./csu/../csu/libc-start.c:360:3
  23:     0x65481ebd4f15 - _start
  24:                0x0 - <unknown>
thread caused non-unwinding panic. aborting.
error: test failed, to rerun pass `-p zenoh --test atexit`

Caused by:
  process didn't exit successfully: `/home/hatter/work/repos/zenoh/target/debug/deps/atexit-f97afb099485217a spawn_in_atexit_main --exact --show-output` (signal: 6, SIGABRT: process abort signal)

 *  The terminal process "cargo 'test', '--package', 'zenoh', '--test', 'atexit', '--', 'spawn_in_atexit_main', '--exact', '--show-output'" terminated with exit code: 101. 
 *  Terminal will be reused by tasks, press any key to close it. 

Metadata

Metadata

Assignees

Labels

C-bugCategory: This is a bug.T-libsRelevant to the library team, which will review and decide on the PR/issue.regression-untriagedUntriaged performance or correctness regression.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions