Closed
Description
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();
}
Metadata
Metadata
Assignees
Labels
No labels