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

unsafe lazy_static that's not Sync ? #135

Closed
asomers opened this issue Dec 9, 2018 · 4 comments
Closed

unsafe lazy_static that's not Sync ? #135

asomers opened this issue Dec 9, 2018 · 4 comments

Comments

@asomers
Copy link

asomers commented Dec 9, 2018

would it be possible to create an unsafe version of the macro that allows the type to be non-Sync? I would like to use it in an FFI context. The calling C code requires me to provide a global mutable structure containing raw pointers.

@KodrAus
Copy link
Contributor

KodrAus commented Dec 10, 2018

Hi @asomers 👋

An unsafe variant of lazy_static is probably out-of-scope for this library, but you can use Rust's own unsafe mutable static feature to provide a global mutable structure:

struct Pointers {
    a: *mut u8,
    b: *mut u8,
}

impl Pointers {
    const UNINIT: Self = Pointers {
        a: std::ptr::null_mut(),
        b: std::ptr::null_mut(),
    };
}

static mut POINTERS: Pointers = Pointers::UNINIT;

fn main() {
    // Working with 'static mut is unsafe
    // You're responsible for ensuring the mutable state is
    //  only aliased and accessed correctly
    unsafe {
        let pointers = &mut POINTERS;
        
         // Pass through FFI
    }
}

@asomers
Copy link
Author

asomers commented Dec 10, 2018

That helps! It makes it possible, but not easy, to do what I want. Using that technique, I can't initialize the variable with non-const functions like mem::zeroed() or mem::uninitialized(). That's why I was hoping there would be a way to do it with lazy_static. Do you know of any way to initialize non-Sync static variables with mem::zeroed()?

@asomers
Copy link
Author

asomers commented Dec 10, 2018

Ok, I found a great hack. I can run code in a constructor function as soon as my library gets loaded, before the application can access it with dlsym.

#[export_name = "mysymbol"]
pub static mut MYSYMBOL: Option<Foo> = None;

#[link_section = ".init_array"]
pub static INITIALIZE: extern "C" fn() = rust_ctor;

#[no_mangle]
pub extern "C" fn rust_ctor() {
    unsafe {
        MYSYMBOL = Some(Foo::new())
    }
}

Thanks for the help. I'm going to close the issue now.

@benniebendiksen
Copy link

Ok, I found a great hack. I can run code in a constructor function as soon as my library gets loaded, before the application can access it with dlsym.

#[export_name = "mysymbol"]
pub static mut MYSYMBOL: Option<Foo> = None;

#[link_section = ".init_array"]
pub static INITIALIZE: extern "C" fn() = rust_ctor;

#[no_mangle]
pub extern "C" fn rust_ctor() {
    unsafe {
        MYSYMBOL = Some(Foo::new())
    }
}

Thanks for the help. I'm going to close the issue now.

Thank you for this; this really saved me from a multi-day bind. Still, why not just use a mutex around your global mutable var and ditch the unsafe keyword when accessing it?

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

3 participants