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

stack overflow when using rand and lazy_static #35

Closed
alanhoff opened this issue Mar 1, 2018 · 2 comments
Closed

stack overflow when using rand and lazy_static #35

alanhoff opened this issue Mar 1, 2018 · 2 comments
Labels

Comments

@alanhoff
Copy link
Contributor

alanhoff commented Mar 1, 2018

I'm trying to understand why this small program is failing to run:

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate may;
extern crate rand;

use std::collections::HashMap;

lazy_static! {
    static ref DATA: Vec<u8> = vec![rand::random::<u8>()];
}

fn main() {
    let mut entries: HashMap<usize, Vec<u8>> = HashMap::new();

    let task = go!(move || {
        entries.insert(0, DATA.clone());
    });

    task.join().unwrap();
}

This program in particular gives me the error stack overflow detected, size=4096, but if I try to do something more elaborated using shared access to entries it also raises some address boundary errors.

The interesting part is that this single combination is failing but if I use the crates separately they work fine:

// This will work
static ref DATA: Vec<u8> = vec![123];

// Or this
let data = vec![rand::random::<u8>()];
let task = go!(...);

I'm using may 0.2.0 and rand 0.4.2.

@Xudong-Huang
Copy link
Owner

rand is using a big stack size in it's implementation.
for debug version stack usage

coroutine name = None, stack size = 40959,  used size = 9205

for release version

coroutine name = None, stack size = 40959,  used size = 2740

here is the modified test

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate may;
extern crate rand;

use std::io::Read;
use std::collections::HashMap;

// the ThreadRng is using a big stack!
lazy_static! {
    static ref DATA: Vec<u8> = vec![rand::random::<u8>()];
}

// the OsRng is not using a big stack, you can safely use it in coroutine context
/*
lazy_static! {
    static ref DATA: Vec<u8> = {
        use rand::Rng;
        let mut rand = rand::OsRng::new().unwrap();
        vec![rand.gen()]
    };
}
*/
fn main() {
    may::config().set_stack_size(4096*10 - 1);
    let mut entries: HashMap<usize, Vec<u8>> = HashMap::new();

    // force init DATA in the main thread
    // let _ = DATA[0];

    let task = go!(move || {
        entries.insert(0, DATA.clone());
    });

    task.join().unwrap();
    std::io::stdin().read(&mut [0]).ok();
}

the solution is init the DATA in main thread (not in the coroutine context, just like what you did to pass the test), or use the os rand interface which doesn't use a huge stack.

@alanhoff
Copy link
Contributor Author

alanhoff commented Mar 1, 2018

Now it makes perfect sense. Static values declared with lazy_static! only get evaluated once the value is used, that's why lazy (d'oh), and if it's being used inside the coroutine context it also affect's it's stack. I'm such a noob.

Thanks for your time and patience!

@alanhoff alanhoff closed this as completed Mar 1, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants