rustuv: Fix a use-after-free on destruction

The uv loop was being destroyed before the async handle was being destroyed, so
closing the async handle was causing a use-after-free in the uv loop. This was
fixed by moving destruction of the queue's async handle to an earlier location
and then actually freeing it once the loop has been dropped.
This commit is contained in:
Alex Crichton 2013-12-15 22:20:53 -08:00
parent 962af9198f
commit f25c81a51a
2 changed files with 12 additions and 2 deletions

View File

@ -138,6 +138,10 @@ impl QueuePool {
}
Queue { queue: self.producer.clone() }
}
pub fn handle(&self) -> *uvll::uv_async_t {
unsafe { (*self.producer.packet()).handle }
}
}
impl Queue {
@ -180,7 +184,9 @@ impl Drop for State {
fn drop(&mut self) {
unsafe {
uvll::uv_close(self.handle, cast::transmute(0));
uvll::free_handle(self.handle);
// Note that this does *not* free the handle, that is the
// responsibility of the caller because the uv loop must be closed
// before we deallocate this uv handle.
}
}
}

View File

@ -67,9 +67,13 @@ impl Drop for UvEventLoop {
fn drop(&mut self) {
// Must first destroy the pool of handles before we destroy the loop
// because otherwise the contained async handle will be destroyed after
// the loop is free'd (use-after-free)
// the loop is free'd (use-after-free). We also must free the uv handle
// after the loop has been closed because during the closing of the loop
// the handle is required to be used apparently.
let handle = self.uvio.handle_pool.get_ref().handle();
self.uvio.handle_pool.take();
self.uvio.loop_.close();
unsafe { uvll::free_handle(handle) }
}
}