Bug 1371319 - null out pulse pointers on destruction. r?kinetik
To avoid a double freeing of pa_context and pa_threaded_mainloop on
error, null out pointers once the object is freed.
Added assertions that pointer are null after destroy()'ing.
MozReview-Commit-ID: 1Ycmkrc2kWe
--- a/media/libcubeb/cubeb-pulse-rs/src/backend/context.rs
+++ b/media/libcubeb/cubeb-pulse-rs/src/backend/context.rs
@@ -150,23 +150,26 @@ impl Context {
// Return the result.
Ok(ctx)
}
pub fn destroy(&mut self) {
if !self.context.is_null() {
unsafe { self.pulse_context_destroy() };
}
+ assert!(self.context.is_null());
if !self.mainloop.is_null() {
unsafe {
pa_threaded_mainloop_stop(self.mainloop);
pa_threaded_mainloop_free(self.mainloop);
+ self.mainloop = ptr::null_mut();
}
}
+ assert!(self.mainloop.is_null());
}
pub fn new_stream(&mut self,
stream_name: *const c_char,
input_device: cubeb::DeviceId,
input_stream_params: Option<cubeb::StreamParams>,
output_device: cubeb::DeviceId,
output_stream_params: Option<cubeb::StreamParams>,
@@ -394,17 +397,17 @@ impl Context {
pa_context_set_state_callback(self.context, Some(error_state), self as *mut _ as *mut _);
pa_threaded_mainloop_lock(self.mainloop);
pa_context_connect(self.context, ptr::null(), 0, ptr::null());
if !self.wait_until_context_ready() {
pa_threaded_mainloop_unlock(self.mainloop);
self.pulse_context_destroy();
- self.context = ptr::null_mut();
+ assert!(self.context.is_null());
return cubeb::ERROR;
}
pa_threaded_mainloop_unlock(self.mainloop);
}
let version_str = unsafe { CStr::from_ptr(pa_get_library_version()) };
if let Ok(version) = semver::Version::parse(version_str.to_string_lossy().as_ref()) {
@@ -427,16 +430,17 @@ impl Context {
let o = pa_context_drain(self.context, Some(drain_complete), self.mainloop as *mut _);
if !o.is_null() {
self.operation_wait(ptr::null_mut(), o);
pa_operation_unref(o);
}
pa_context_set_state_callback(self.context, None, ptr::null_mut());
pa_context_disconnect(self.context);
pa_context_unref(self.context);
+ self.context = ptr::null_mut();
pa_threaded_mainloop_unlock(self.mainloop);
}
pub fn operation_wait(&self, stream: *mut pa_stream, o: *mut pa_operation) -> bool {
unsafe {
while pa_operation_get_state(o) == PA_OPERATION_RUNNING {
pa_threaded_mainloop_wait(self.mainloop);
if !PA_CONTEXT_IS_GOOD(pa_context_get_state(self.context)) {