Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tokio LocalSet can no longer be stored in thread_local #4973

Closed
futursolo opened this issue Sep 4, 2022 · 3 comments · Fixed by #4976
Closed

Tokio LocalSet can no longer be stored in thread_local #4973

futursolo opened this issue Sep 4, 2022 · 3 comments · Fixed by #4976
Labels
A-tokio Area: The main tokio crate C-bug Category: This is a bug. M-task Module: tokio/task

Comments

@futursolo
Copy link

Version

tokio 1.21.0

Platform

  • aarch64-unknown-linux-gnu
  • x86_64-unknown-linux-gnu

Description

The following code runs fine with 1.20.1 but panics in 1.21.0.

I tried this code:

use std::thread;

use tokio::runtime::Handle;
use tokio::sync::oneshot;
use tokio::task::LocalSet;

thread_local! {
    static LOCAL_SET: LocalSet = LocalSet::new();
}

#[tokio::main]
async fn main() {
    // holds runtime thread until end of main fn.
    let (_tx, rx) = oneshot::channel::<()>();
    let handle = Handle::current();

    thread::spawn(move || {
        LOCAL_SET.with(|local_set| {
            handle.block_on(local_set.run_until(async move {
                let _ = rx.await;
            }))
        });
    });
}

I expected to see this happen:

The code should run as normal.

Instead, this happened:

thread '<unnamed>' panicked at 'cannot access a Thread Local Storage value during or after destruction: AccessError', /rustc/4b91a6ea7258a947e59c6522cd5898e7c0a6a88f/library/std/src/thread/local.rs:421:26
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
fatal runtime error: failed to initiate panic, error 3450452000
Aborted
@futursolo futursolo added A-tokio Area: The main tokio crate C-bug Category: This is a bug. labels Sep 4, 2022
@Noah-Kennedy
Copy link
Contributor

Thanks for reporting this!

I have a few ideas as to what did this. I'm going to go and run a bisect.

@Darksonn
Copy link
Contributor

Darksonn commented Sep 5, 2022

This is probably caused by #4765, but I don't really understand how this was not already an issue. Perhaps that PR somehow changes the order in which the thread-locals are destroyed?

Anyway, I've opened a PR that should fix this.

@Forsworns
Copy link

Forsworns commented Oct 31, 2022

Version

tokio 1.21.2

Platform

x86_64-unknown-linux-gnu

Description

seems met a similar problem. Here is my code, is the error expected?

Or should I simply move the struct Runtime and struct LocalSet outside the struct TokioLocalSet? Just as what futursolo does. (Also panic, the same error message)

And I don't understand why main3 works while main1 panics.

Here is the link to the playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=e26d1f993906627a219d304e849cc70b

@Darksonn

// src/main.rs
use tokio::runtime::Runtime;
use tokio::task::LocalSet;

thread_local! {
    pub static LOCAL_SET: TokioLocalSet = TokioLocalSet::new();
}

pub struct TokioLocalSet {
    rt: Runtime,
    local: LocalSet,
}

impl TokioLocalSet {
    pub fn new() -> TokioLocalSet {
        TokioLocalSet {
            rt: tokio::runtime::Builder::new_current_thread()
                .enable_all()
                .build()
                .unwrap(),
            local: LocalSet::new(),
        }
    }

    async fn inner_method(&self) {
        self.local
            .run_until(async move {
                tokio::task::spawn_local(async {});
            })
            .await
    }

    pub fn method(&self) {
        self.rt.block_on(self.inner_method());
    }
}

fn main1(){
    // will panic
    LOCAL_SET.with(|f|{
        f.method();
    });
}

fn main2(){
    // work well
    let ls = TokioLocalSet::new();
    ls.method();
}

fn main3(){
    // work well
    let ls = TokioLocalSet::new();
    ls.method();
    LOCAL_SET.with(|f|{
        f.method();
    });
}
# Cargo.toml
[package]
name = "tokio_local_set"
version = "0.1.0"
edition = "2021"

[dependencies]
tokio = { version = "1.21.2", features = ["full"] }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-tokio Area: The main tokio crate C-bug Category: This is a bug. M-task Module: tokio/task
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants