edef1c / libfringe

a Rust library implementing safe, lightweight context switches, without relying on kernel services
https://edef1c.github.io/libfringe
Apache License 2.0
512 stars 31 forks source link

Crash when non-move closure passed to Generator::new #65

Open rhn opened 7 years ago

rhn commented 7 years ago

Using a move closure inside a struct::fn which borrows a struct field results in corrupted memory when that closure is not move.

Example:

extern crate fringe;
use std::iter::Iterator;
use fringe::generator::Yielder;
use fringe::{OsStack, Generator};

struct Gpx {
    creator: String,
}

type Generator_<T> = fringe::Generator<(), T, fringe::OsStack>;

impl Gpx {
    pub fn events<'a>(&'a self) -> Generator_<&'a str> {
        let stack = OsStack::new(1 << 24).unwrap();
        Generator::new(stack, |ctx, ()| { // broken
        // Generator::new(stack, move |ctx, ()| { // working
            ctx.suspend(self.creator.as_str());
        })
    }
}

fn main() {
    let data = Gpx{ creator: String::from("xyz") };
    println!("{:?}", data.events().next());
}

Unfortunately, I don't know if it's a problem with type checking or the unsafe portion. Given some pointers, I will try to debug it myself.

edef1c commented 7 years ago

That's.. surprising. The generator shouldn't be able to outlive the captures.

edef1c commented 7 years ago

Ah. This is fixed in master (intended to be released as 2.x), but we had a bunch of stuff blocking the release, and then real life intervened.. Time to pick that back up I guess.