-
Notifications
You must be signed in to change notification settings - Fork 19
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
ScopedCoroutine
is unsound
#27
Comments
To my estimates |
This is unsound because it allows values on the stack to be forgotten without running their associated drop code, which is unsound for constructs like scoped threads. Fixes #27
This is unsound because it allows values on the stack to be forgotten without running their associated drop code, which is unsound for constructs like scoped threads. Fixes #27
Also the regular #!/usr/bin/env -S cargo +nightly -Zscript
---
[package]
edition = "2021"
[dependencies]
corosensei = "0.1.4"
scoped-tls = "1.0.1"
---
use std::{mem::forget, sync::mpsc};
use corosensei::Coroutine;
use scoped_tls::scoped_thread_local;
scoped_thread_local!(static S: String);
fn main() {
let mut s = "Happy".to_owned();
let (tx1, rx1) = mpsc::sync_channel(1);
let (tx2, rx2) = mpsc::sync_channel(1);
S.set(&s, || {
let mut coroutine = Coroutine::new(|yielder, ()| {
S.with(|s| {
let s = s.as_str();
std::thread::scope(move |scope| {
let _thrd = scope.spawn(move || {
rx1.recv().unwrap();
tx2.send(s.to_owned()).unwrap();
});
let () = yielder.suspend(());
});
})
});
coroutine.resume(());
forget(coroutine);
});
s.clear();
s.push_str("Sad");
tx1.send(()).unwrap();
let data_race_s = rx2.recv().unwrap();
dbg!(&s, &data_race_s);
} |
Surprisingly my #!/usr/bin/env -S cargo +nightly -Zscript
---
[package]
edition = "2021"
[dependencies]
corosensei = "0.1.4"
scope-lock = "0.2.5"
---
use std::{mem::forget, sync::mpsc};
use corosensei::Coroutine;
fn main() {
let mut s = "Happy".to_owned();
let (tx1, rx1) = mpsc::sync_channel(1);
let (tx2, rx2) = mpsc::sync_channel(1);
scope_lock::lock_scope(|e| {
let s = s.as_str();
let clone_s = e.fn_once(Box::new(|()| s.to_owned()));
let mut coroutine = Coroutine::new(|yielder, ()| {
std::thread::scope(move |scope| {
let _thrd = scope.spawn(move || {
rx1.recv().unwrap();
tx2.send(clone_s(())).unwrap();
});
let () = yielder.suspend(());
});
});
coroutine.resume(());
forget(coroutine);
});
s.clear();
s.push_str("Sad");
tx1.send(()).unwrap();
let data_race_s = rx2.recv().unwrap();
dbg!(&s, &data_race_s);
} I guess the issue is that the Interestingly if you implement |
Sorry, I've found it just yesterday, didn't report it in #28. Example of UB without use std::{mem::forget, sync::mpsc};
use corosensei::Coroutine;
fn main() {
let mut s = "Happy".to_owned();
let (tx1, rx1) = mpsc::sync_channel(1);
let (tx2, rx2) = mpsc::sync_channel(1);
{
let s = s.as_str();
let mut coroutine = Coroutine::new(|yielder, s: &str| {
std::thread::scope(move |scope| {
let _thrd = scope.spawn(move || {
rx1.recv().unwrap();
tx2.send(s.to_owned()).unwrap();
});
yielder.suspend(());
panic!();
});
});
coroutine.resume(s);
forget(coroutine);
}
s.clear();
s.push_str("Sad");
tx1.send(()).unwrap();
let data_race_s = rx2.recv().unwrap();
dbg!(&s, &data_race_s);
} Basically there should be |
Prints out:
The text was updated successfully, but these errors were encountered: