Skip to content

Crash in cleanup_task_local_map when the map contains a closure with a managed box whose destructor accesses the task local data #8693

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

Closed
larsbergstrom opened this issue Aug 23, 2013 · 6 comments

Comments

@larsbergstrom
Copy link
Contributor

When there is a closure that captures a managed box with a destructor, stores that closure in the task local data, and then the destructor for that managed box also tries to touch the task local data, there will be a crash (accessing freed memory) during shutdown in cleanup_task_local_map, and occasionally some warnings about leaked memory.

Below is a small example that uses glfw_rs. When callbacks are set in that module, they are registered in a HashMap in task local storage, and the destructor for the Window struct removes them from that HashMap.

extern mod glfw;

#[start]
fn start(argc: int, argv: **u8, crate_map: *u8) -> int {
    std::rt::start_on_main_thread(argc, argv, crate_map, main)
}

pub struct Wrapper {
    glfw_window: glfw::Window
}

impl Wrapper {
    /// Creates a new window.                                                                                                                   
    fn new() -> @mut Wrapper {
        // Create the GLFW window.                                                                                                              
        let glfw_window = glfw::Window::create(800, 600, "Servo", glfw::Windowed).unwrap();
        glfw_window.make_context_current();

        // Create our window object.                                                                                                            
        let window = @mut Wrapper {
            glfw_window:glfw_window,
        };

        // BUG: If the captured use of window is changed to instead use the provided win argument,                                              
        // then there is no crash during the destructor. However, the change in servo is not that                                               
        // simple. as the Wrapper struct has significantly more data and functionality, which are                                               
        // used in the event handlers.                                                                                                          
        do window.glfw_window.set_key_callback |_win, key, _scancode, action, _mods| {
            if action == glfw::PRESS && key == glfw::KEY_ESCAPE {
                window.glfw_window.set_should_close(true);
            }
        }
        window
    }

    fn recv(&self) -> bool {
        glfw::poll_events();
        if self.glfw_window.should_close() {
            true
        } else {
            false
        }
    }

}

fn main() {
    glfw::init();

    let window: @mut Wrapper = Wrapper::new();

    // Enter the main event loop.                                                                                                               
    while !window.recv() {
    }
    glfw::terminate();
}
@alexcrichton
Copy link
Member

I believe that this would be fixed by #8447, but there's still a question of whether accessing TLS from when TLS is getting destroyed is even a legal operation. If TLS destruction creates always creates more TLS, you never can actually destroy TLS...

@alexcrichton
Copy link
Member

By fixed I mean it probably won't crash (haven't tested it)

@larsbergstrom
Copy link
Contributor Author

Thanks! I'm going to change the module to avoid using the TLS in during destruction, but am glad to hear that the fix should clean up this issue.

@alexcrichton
Copy link
Member

@larsbergstrom, can you confirm whether this is fixed now or not? The problem of TLS attempting to access TLS during destruction I believe is a separate issue from this one.

@larsbergstrom
Copy link
Contributor Author

@alexcrichton Yes, we've worked around this specific case by changing glfw-rs to no longer use TLS and destructors in this fashion. If you've got the more general case logged elsewhere (what to do about TLS access during a destructor being run as a result of task shutdown), I'm fine with closing it.

@alexcrichton
Copy link
Member

Cool, thanks! Closing in favor of #8302

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