8000 Safe sendable `Generator` is unsound · Issue #58 · Xudong-Huang/generator-rs · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Safe sendable Generator is unsound #58

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

Open
zetanumbers opened this issue May 21, 2024 · 2 comments
Open

Safe sendable Generator is unsound #58

zetanumbers opened this issue May 21, 2024 · 2 comments

Comments

@zetanumbers
Copy link
zetanumbers commented May 21, 2024

Sadly sendable Generator is currently unsound because thread local variables may leak non-sendable values from within the our coroutine. Here's example:

#![forbid(unsafe_code)]

use std::{cell::Cell, rc::Rc, thread};

use generator::Gn;

const COUNT_ITERATIONS: u64 = 1000000000;

fn main() {
    thread_local! {
        static COUNTER: Cell<Option<Rc<Cell<u64>>>> = Cell::new(None);
    }

    let counter = Rc::new(Cell::new(0));
    COUNTER.with(|tl| tl.set(Some(Rc::clone(&counter))));

    let mut generator = Gn::new_scoped(move |mut s| {
        let counter = COUNTER.with(|tl| tl.take()).unwrap();
        s.yield_with(());
        println!("Rc {:p} in thread {:?}", counter, thread::current());
        for _ in 0..COUNT_ITERATIONS {
            counter.set(counter.get() + 1)
        }
    });
    generator.next().unwrap();

    let child = thread::spawn(move || {
        generator.next().unwrap();
    });

    println!("Rc {:p} in thread {:?}", counter, thread::current());
    for _ in 0..COUNT_ITERATIONS {
        counter.set(counter.get() + 1)
    }

    child.join().unwrap();
    assert_eq!(counter.get(), 2 * COUNT_ITERATIONS);
}

Output:

Rc 0x60000058d210 in thread Thread { id: ThreadId(1), name: Some("main"), .. }
Rc 0x60000058d210 in thread Thread { id: ThreadId(2), name: None, .. }
thread 'main' panicked at src/main.rs:37:5:
assertion `left == right` failed
  left: 1028478159
 right: 2000000000

See https://blaz.is/blog/post/lets-pretend-that-task-equals-thread/ and https://users.rust-lang.org/t/controversial-opinion-keeping-rc-across-await-should-not-make-future-send-by-itself/100554/12 for details.

@zetanumbers
Copy link
Author

Added the example

7D75

@Xudong-Huang
Copy link
Owner

This is a long known issue. This is why may spawn is unsafe. You should use coroutine_local! here. And I have no better idea to design the API, do you have any suggestions?

@zetanumbers zetanumbers changed the title Sendable Generator is unsound Safe sendable Generator is unsound Jun 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants
0