Skip to content

Out of Memory is triggered if using Rust Local Thread Storage (LTS)

Rustc version: redox-2025-01-12 after cookbook!560 (merged)

A simple compilation with test.rs in dev config with rustc will trigger allocation until the kernel triggers OOM

user:~$ rustc test.rs

thread 'rustc' panicked at /mnt/redox/cookbook/recipes/dev/rust/source/library/std/src/thread/local.rs:272:26:
cannot access a Thread Local Storage value during or after destruction: AccessError

error: the compiler unexpectedly panicked. this is a bug.

note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md

note: please make sure that you have updated to the latest nightly

note: please attach the file at `/home/user/rustc-ice-2025-07-25T06_46_42-75.txt` to your bug report

query stack during panic:
KERNEL PANIC: panicked at src/memory/mod.rs:1017:34:
not yet implemented: oom
  FP ffff800027f2fca0: PC ffffffff80029f32
    FFFFFFFF80029DE0+0152
    rust_begin_unwind
  FP ffff800027f2fd80: PC ffffffff800a2a5f
  FP ffff800027f2fdb0: PC ffffffff800488bd
  FP ffff800027f2fe20: PC ffffffff8008f830
    FFFFFFFF8008F7F0+0040
    kernel::arch::x86_64::interrupt::exception::page::inner
  FP ffff800027f2ff50: PC ffffffff80083117
    FFFFFFFF800830E0+0037
    kernel::arch::x86_64::interrupt::exception::page
  0000000ab5555ffe: GUARD PAGE
CPU #0, CID 0xffffff7f80032210
NAME: /usr/bin/rustc, DEBUG ID: 88
HALT

The error source mentions source/library/std/src/thread/local.rs:272, which is:

    /// Acquires a reference to the value in this TLS key.
    ///
    /// This will lazily initialize the value if this thread has not referenced
    /// this key yet.
    ///
    /// # Panics
    ///
    /// This function will `panic!()` if the key currently has its
    /// destructor running, and it **may** panic if the destructor has
    /// previously been run for this thread.
    ///
    /// # Examples
    ///
    /// ```
    /// thread_local! {
    ///     pub static STATIC: String = String::from("I am");
    /// }
    ///
    /// assert_eq!(
    ///     STATIC.with(|original_value| format!("{original_value} initialized")),
    ///     "I am initialized",
    /// );
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn with<F, R>(&'static self, f: F) -> R
    where
        F: FnOnce(&T) -> R,
    {
        self.try_with(f).expect( // <-------------------------------
            "cannot access a Thread Local Storage value \
             during or after destruction",
        )
    }

I cannot obtain the backtrace, hence I don't know what f is passed here.

Fortunately, we can disable LTS as it's also not available in all platform. To disable it, we can turn it off at: source/compiler/rustc_target/src/spec/base/redox.rs:

pub(crate) fn opts() -> TargetOptions {
    TargetOptions {
        os: "redox".into(),
        env: "relibc".into(),
        dynamic_linking: true,
        families: cvs!["unix"],
        has_rpath: true,
        position_independent_executables: true,
        relro_level: RelroLevel::Full,
        has_thread_local: false, // <--------- set this to false
        crt_static_default: true,
        crt_static_respected: true,
        crt_static_allows_dylibs: true,
        late_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-lgcc"]),
        ..Default::default()
    }
}
Edited by Wildan Mubarok